興緻勃勃地定義了下面這麼個建構函式:
複製代碼 代碼如下:var Coder = function( nick ){
this.nick = nick;
};
定義建構函式結束後呢?沒錯,趕緊執行個體化:
var coder = Coder( 'casper' );
這個coder兄弟叫什麼名字?趕緊列印下: 複製代碼 代碼如下:console.log( coder.nick ); //undefined
= =b 竟然是undefined!!再回過頭看看執行個體化的那個語句,不難發現問題出在哪裡:少了個new
var coder = Coder( 'casper' ); //當作普通的函數來調用,故內部的this指標其實指向window對象
console.log( window.nick); //輸出:casper
var coder = new Coder( 'casper' ); //加上new,一切皆不同,this正確地指向了當前建立的執行個體
console.log( coder.nick ); //輸出:casper
關於this指標的指向問題不是本文討論的內容,可以參考下犀牛書相關章節
這樣的錯誤貌似挺低級的,但出現的機率挺高的,腫麼去避免或減少這種情況的發生呢?
可以在內部實現裡面動下手腳: 複製代碼 代碼如下:var Coder = function( nick ){
if( !(this instanceof Coder) ){
return new Coder( nick );
}
this.nick = nick;
};
其實很簡單,執行個體化的時候,內部判斷下,當前this指向的對象的類型即可,如果非當前建構函式的類型,強制重新調用一遍建構函式。
突然覺得Coder這名字不夠洋氣?想用Hacker,好吧,我改。。。數了下,一共有三處要改,這不科學,有沒有辦法只把建構函式的名字改了就行?
當然有: 複製代碼 代碼如下:var Coder = function( nick ){
if( !(this instanceof arguments.callee) ){
return new arguments.callee( nick );
}
this.nick = nick;
};
tips:據說在ES 5的strict 模式下面arguments.callee會被禁用,不過僅當ES 5普及同時你指定了要使用strict 模式,否則還是可以用的發散下思維:在JQ裡麵包打天下所向披靡的$,大家都知道它會返回一個jquery對象,如下:
var jObject = $('#node_id');
有沒有發現,這裡同樣沒有new!應該猜到怎麼回事了吧。原理是差不多的,不過裡面的實現要複雜得多,有空再把JQ裡面的實現拔下寫下總結