興致勃勃地定義了下面這麼個構造函數:
復制代碼 代碼如下:
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的嚴格模式下面arguments.callee會被禁用,不過僅當ES 5普及同時你指定了要使用嚴格模式,否則還是可以用的發散下思維:在JQ裡面包打天下所向披靡的$,大家都知道它會返回一個jquery對象,如下:
var jObject = $('#node_id');
有沒有發現,這裡同樣沒有new!應該猜到怎麼回事了吧。原理是差不多的,不過裡面的實現要復雜得多,有空再把JQ裡面的實現拔下寫下總結