javascript
是一門弱語言,他有着分同通常的靈活性使它迅速的成爲幾乎人人必會的一門語言,but,大家使用的姿式真的正確嗎?javascript
在之前的開發過程中,老闆:給我加個驗證用戶郵箱
、驗證用戶短信...
功能!java
function checkMessage(){...} function checkEmail(){...} function ... //茫茫多的函數
這樣寫好了以後 function
是全局的變量,那麼是全局的就不免會對項目javascript環境形成污染,可能會對其餘同事形成影響,咱們首先要考慮會不會影響別人,若是別人重名對你的checkMessage
覆蓋,那麼這樣的BUG是很難發現的。爲了避免形成太多的全局污染
,咱們能夠這樣寫:編程
var checkObject = { checkMessage:function(){}, checkEmail:function(){}, ... }
首先說明,並非這樣寫就不會形成污染了,checkObject
依舊是全局變量,那麼好處在哪裏呢?想一下若是Jquery的$
被覆蓋了,那麼咱們頁面的後端
$.each | $.extends | $(#id) | $...
都失效了,那麼咱們很容易定位問題: Jquery
出問題了!checkObject
也是同樣,當checkObject出問題了,咱們很容易定位錯誤。設計模式
調用:checkObject.checkMessage()
便可框架
那麼問題又來了:若是有同事用個人checkObject搞一些事情呢?它能夠直接用個人方法麼?固然能夠,問題是,你買了一本書你願意別人亂寫亂畫麼?咱們能夠改造一下:函數
var checkObject = function(){ return { checkMessage:function(){}, checkEmail:function(){}, ... } }
咱們把方法經過function
的調用返回,這樣別人能夠這樣用 :this
var check = checkObject(); check.checkEmail();
咱們能夠再完善一下,把checkObject
當作java的類,checkMessage
,checkEmail
當作java的public
公有方法,既然當作類了,咱們能夠把checkObject
寫成大寫CheckObject
spa
var CheckObject = function(){ this.checkMessage = function(){}, this.checkEmail = function(){}, ... }
別人調用:prototype
var check = new CheckObject(); //既然是一個類了,就要 new 來實例化了 check.checkEmail();
每一次經過new
建立新對象的時候,新建立的對象都會對類this
上的屬性進行復制,你定義了兩個那麼就複製兩次,那麼再更多呢?是否是感受有些奢侈呢,考慮咱們能夠運用javascript的原型prototype
來建立它:
var CheckObject = function(){ } CheckObject.prototype.checkMessage = function(){}, CheckObject.prototype.checkEmail = function(){}, ...
你嫌麻煩?
var CheckObject = function(){ } CheckObject.prototype{ checkMessage : function(){}, checkEmail : function(){}, ... }
這樣咱們的方法都複製到CheckObject
的原型連上去了,建立出來的對象都是經過prototype
依次尋找,都綁定在CheckObject
的原型上__proto__
隨便看一下Jquery
的原型鏈,是否是很熟悉的方法呢?
同志們是否好奇Jquery
的方法是如何鏈式調用的呢?很簡單,我來模擬一下
var CheckObject = function(){ } CheckObject.prototype = { checkMessage : function(){ ... return this }, checkEmail : function(){ ... return this }, ... var check = new CheckObject(); check.checkMessage().checkEmail();
就這麼簡單,咱們只須要將this
指代的當前對象所有返回便可。
咳咳,言歸正傳,回到面向對象編程的課題上
java中有 private
聲明的私有變量、 有經過public
的getter
setter
方法進行通訊,有static
修飾的靜態變量
,靜態方法
,有構造器
,那麼javascript可使用這樣的設計模式麼?能夠,跟我往下看:
咱們去商店買菸
var Smoke = function(id,name){ //私有屬性 var num = 0; //對象的公有屬性 (須要new) this.id = id; //私有方法 function checkID(){ return true}; //公有 setter getter 構造函數 this.setName = function(name){ this.name = name; } this.getName = function(){ return this.name; } //對象的公有屬性 (須要new) this.information = function(){ //只有在Smoke內部才能調用checkID() if(checkID()) return this.name+'香菸'+'訂單號 :'+this.id } } Smoke.prototype = { money:'10元', //公有屬性(不須要new) 直接Smoke.money[想沒想到Array的length?] other:function(){} } var smoke = new Smoke(994857,'煊赫門'); smoke.information(); //"undefined香菸訂單號 :994857" ps:由於咱們沒對Smoke的name屬性賦值 smoke.setName('煊赫門'); //咱們賦值 smoke.information(); //"煊赫門香菸訂單號 :994857" smoke.num; //undefined ps:很明顯他是私有屬性 smoke.checkID();//error is not function ps:很明顯私有方法
若是咱們沒有new
var smoke = Smoke(994857,'煊赫門'); smoke.information(); //Uncaught TypeError: Cannot read property 'information' of undefined
納尼報錯了?
smoke.money; //undefind smoke //undefind
(好像明白了什麼......) 別急,讓咱們看下window
window.information(); // "undefined香菸訂單號 :994857"
恍然大悟,由於new是能夠對當前對象(Smoke)的this
不停地賦值【上面講過】,而上面的沒有new
至關於全局執行了Smoke()
因此是他的this
指向到 window
去了!
怎麼避免這種無操做呢?咱們在Smoke內部進行類型檢查:
var Smoke = function(id,name){ var num = 0; function checkID(){ return true}; //判斷this在執行過程當中是否是屬於Smoke,若是是說明是new過的 0.0 if(this instanceof Smoke){ this.id = id; this.setName = function(name){ this.name = name; } this.getName = function(){ return this.name; } //對象的公有屬性 (須要new) this.information = function(){ //只有在Smoke內部才能調用checkID() if(checkID()) return this.name+'香菸'+'訂單號 :'+this.id } }else{ return new Smoke(id,name);//內部從新new一個 0.0 } }
看完了麼,感受爽不,是否是感受就是在寫java呢,其實javascript就是靈活在這裏,這只是javascript一種經常使用的面向對象設計模式,後面我會將更多的設計模式,這些設計模式都是通過前人無數心血總結出來給咱們的,咱們爲何不用呢?
感謝[他竟然愛吃蟲]
同窗對本文的校對
若是您以爲還算不錯能夠關注我持續看個人文章,大概方向:先後端語言設計模式
、如何設計好一款框架
、源碼導讀
、技術實踐
。
147255248