功能上,這樣構造我的代碼有沒有什麼缺點? 將原型方法添加到 構造函數的正文中(即構造函數的 表達式語句關閉之前)是否會導致意外的作用域問題?
是的,有缺陷和意想不到的範圍界定問題。
遍地本地定義的功能分配的原型,無論重複該分配,並創建一個新的功能對象中的每個的時間。之前的作業將被垃圾收集,因爲它們不再被引用,但在構造函數的運行時執行和垃圾收集方面與第二個代碼塊相比,這是不必要的。
在某些情況下會出現意外的範圍界定問題。請參閱我的答案末尾的Counter
示例以獲得明確示例。如果您從原型方法引用構造函數的局部變量,那麼您的第一個示例會在您的代碼中創建一個潛在的令人討厭的錯誤。
還有一些其他的(更小的)差異。你的第一個計劃禁止構造之外使用原型爲:
Filter.prototype.checkProduct.apply(someFilterLikeObject, ...)
,當然,如果使用的人:
Object.create(Filter.prototype)
而不運行Filter
構造,這也將創造一個不同結果可能不太可能,因爲期望使用Filter
原型的東西應該運行Filter
構造函數以實現預期結果是合理的。
從一個運行時的性能點(調用對象的方法的性能),你會用這個更好:
var Filter = function(category, value){
this.category = category;
this.value = value;
// product is a JSON object
this.checkProduct = function(product){
// run some checks
return is_match;
}
};
有一些JavaScript「專家」誰主張不再需要使用原型的內存節省(我前幾天觀看了關於該原型的視頻講座),所以現在是時候開始直接在對象上使用更好的方法性能,而不是原型。我不知道我是否準備好自己主張,但這是一個值得思考的問題。
你的第一個方法,我能想到的最大的缺點是,它是真的,真的很容易使一個討厭的編程錯誤。如果您碰巧認爲您可以利用原型方法現在可以看到構造函數的局部變量這一事實,只要您有一個以上的對象實例,就會立即將自己拍攝下來。想象一下這樣的情況:這個問題的
var Counter = function(initialValue){
var value = initialValue;
// product is a JSON object
Counter.prototype.get = function() {
return value++;
}
};
var c1 = new Counter(0);
var c2 = new Counter(10);
console.log(c1.get()); // outputs 10, should output 0
示範:http://jsfiddle.net/jfriend00/c7natr3d/
這是因爲,雖然它看起來像get
方法形成一個封閉且具有訪問實例變量,這些變量構造函數的局部變量,它在實踐中並不這樣。因爲所有實例共享相同的原型對象,所以Counter
對象的每個新實例都會創建一個get
函數的新實例(它可以訪問剛創建的實例的構造函數局部變量)並將其分配給原型,所以現在所有實例有一個get
方法可以訪問創建的最後一個實例的構造函數的局部變量。這是一場程序設計的災難,因爲這可能從來都不是想要的,而且很容易就能成爲頭腦清醒的人,弄清楚出了什麼問題以及爲什麼。
我想到的是Filter的原型在Filter被調用之前一直是空的。如果有人希望繼承Filter過濾器原型但不先調用Filter?但我不確定這是否值得完整答案。 :) – 2015-01-31 20:09:56
您正在重新運行每次調用構造函數時設置原型的所有代碼。 – Pointy 2015-01-31 20:10:10
每次構造函數被調用時,它會一遍又一遍地運行相同的賦值,所以在這方面有點浪費。也許別人可以想到一個實際上會導致功能問題的情況,但我不能。 – jfriend00 2015-01-31 20:10:17