這個怎麼樣簡單的通用模式(我的最愛)?
(function(){ //IIF constructor builder
(this[arguments[0]]= function(/*args*/){ //The constructor
/*constructor payload code*/
}).prototype= { //Methods & Properties to inherit:
method_1: function(){ /*your code*/ } //method 1
, method_2: function(){ /*your code*/ } //method 2
, property_1: /*your code*/ //property 1
, property_2: /*your code*/ //property 2
};
})(/*constructor identifier*/);
this
將引用運行此構建函數的上下文。所以,如果構造函數生成器對window
運行,那麼window
將有全球功能$elect
。所以你也可以在你的模塊化系統中使用這種模式。
更新:
你問
instanceof
(和你提供的代碼來看,你需要它,人們可以調用構造函數時省略
new
)。
這可能會讓事情變得更棘手。
對我個人而言,'users'!=='coders'和'coders'(誰編寫代碼(使用x庫)供用戶使用)應該知道何時使用new
。
雖然它可能是有用的,在開發過程中throw new
/console.log
/alert
錯誤,應該在最後的(最小化/優化)的生產代碼不需要這個(除非你的觀點是,你有很多的new
陳述,可以省略,所以你的代碼可以進一步縮小)。
首先,你必須決定是否要爲
執行速度和使用的new
優化(代碼通常運行?):
if(/*called with new*/){
/*constructor payload code*/
} else {
/*error code*/
}
或最小的文件大小是缺乏new
在執行速度的代價(代碼運行只是一對夫婦的次):
if(!(/*called with new*/)){ /*error code*/ }
/*constructor payload code*/
注意的是最後的選擇也可能是更實際的註釋掉/刪除生產代碼,如果您打算要求使用new
,提供最快的執行速度。
線/*called with new*/
可以用this instanceof arguments.callee
雖然arguments.callee
是一個很好的通用的解決方案(因爲沒有被硬編碼/命名),它會拋出異常來代替,如果你'use strict';
- 模式,因爲它現在已經過時(出於某種原因)在favor of named function expressions(根據約翰Resig的,一個也使用在未來expression this function
)。
MDN specifies that a function name can be used only within the function's body,所以嚴格的模式,我們可以(在下面的例子C
)命名我們(以前匿名)功能
和檢查(而不是this instanceof arguments.callee
)this instanceof C
:
(function(){ //IIF constructor builder
(this[arguments[0]]= function C(id){ //The constructor
if(!(this instanceof C)){ /*error code*/ } //Catch ID-10-T Error
/*constructor payload code*/
}).prototype= { //Methods & Properties to inherit:
method_1: function(){ /*your code*/ } //method 1
, method_2: function(){ /*your code*/ } //method 2
, property_1: /*your code*/ //property 1
, property_2: /*your code*/ //property 2
};
})('$elect');
如果/*error code*/
只是阻止無聲錯誤由:
alert
/console.log
/throw new Error
('Error: forgot new')
然後直到現在這種模式(既嚴格和非ST rict變體)是非常通用的。
如果您想通過返回適當的新對象(除了現在對編碼器的可選警告)來「修復」調用,那麼必須考慮傳遞給構造函數的參數(如果有的話)。
因此,對於那些不要求參數的構造函數,你/*error code*/
應該包含:
return new arguments.callee();
非嚴格或
return new C();
對於希望嚴格
構造函數(可選)命名參數,您/*error code*/
應該讓它們硬編碼,如:
return new arguments.callee(arg_1, arg_2 /*,etc..*/);
用於非嚴格或
return new C(arg_1, arg_2 /*,etc..*/);
嚴格
作爲例子:
(function(){ //IIF constructor builder
(this[arguments[0]]= function C(id){ //The constructor
if(!(this instanceof C)) return new C(id); //Fix ID-10-T Error
this.elm= document.getElementById(id);
}).prototype= { //Methods & Properties to inherit:
show: function(){ //Method show
this.elm.style.display= '';
}
, hide: function(){ //Method hide
this.elm.style.display= 'none';
}
, toggle: function(){ //Method toggle
this[this.elm.style.display ? 'show' : 'hide']();
}
};
})('$elect');
我目前沒有意識到一個簡單而優雅的方式來傳遞任何(對於firefox最多256)非硬編碼未知(預期/可選/命名)參數(缺少一個單一數組/對象作爲第一個參數)。問題是,arguments
是一個數組(類似)的對象,所以不能簡單地通過它像return new C(arguments);
.apply()
到一個人可能會想到的救援,因爲它接受一個參數數組作爲第二個參數(不像.call()
需要逗號 - 但是可惜:new
和apply
/call
不能一起使用1,2 ...(有人,請留下評論,如果你知道一個優雅的解決方案,適合這種模式,謝謝)
最後一個小變化(和可能的應用)到上述模式。主要的區別是,這種模式會返回一個構造函數(這樣你就可以簡單地指明引用它的變量)(而不是直接設置構造上面的圖案):
var myLibrary= {
$elect: (function(C){
(C= function(id){
if(!(this instanceof C)) return new C(id);
this.elm= document.getElementById(id);
}).prototype= {
addBorder: function(col){
this.elm.style.border='1px solid '+col;
}
, delBorder: function(){
this.elm.style.border='';
}
}; return C;
})()
, var_foo: 'foo'
, var_bar: 'bar'
};
Example fiddle here。
希望這會有所幫助!
所以你想分配屬性到一個原型中,但是能夠動態地選擇哪個對象的原型來將它們添加到這些行中? –
就是這樣的。那麼,我也應該能夠改變構造函數的名字。使用'selector'變量。 – akinuri