which one is correct?
這取決於你如何看待 「正確」:
- 要麼聲明不能被正確解析?
- 哪一個會計算
calcArea
?
- 代碼1會正確計算它,而代碼2不會創建
Rectangle
類的成員函數,但是您可以通過有點難度的廣告重定向來正確計算它。見下文。
- 是創建類的好習慣嗎?
碼1 - calcArea()
如果您在隨後的代碼1創建Rectangle
的新實例:
function Rectangle(height, width) {
this.height = height;
this.width = width;
this.calcArea = function() { // why use this here?
return this.height * this.width;
};
}
var rect = new Rectangle(3, 4);
console.log(rect.calcArea());
將正確輸出12
代碼2 - calcArea()
如果創建Rectangle
在隨後碼2的新實例:
function Rectangle(height, width) {
this.height = height;
this.width = width;
calcArea = function() {
return this.height * this.width;
};
}
var rect = new Rectangle(3, 4);
console.log(rect.calcArea());
將拋出一個錯誤:TypeError: rect.calcArea is not a function
calcArea
是,而是附着在全球範圍內,所以我們可以做:
console.log(calcArea());
將輸出NaN
爲calcArea
在全球範圍內的一部分,所以沒有一個Rectangle
類的任何實例的知識和全球範圍內不具有height
或width
屬性。
如果我們這樣做:
var rect = new Rectangle(3, 4);
width = 7; // Set in the global scope.
height = 10; // Set in the global scope.
console.log(calcArea());
然後,它會返回70
(而不是12
以來,內calcArea()
,this
引用全球範圍內,而不是rect
對象)。
如果我們改變什麼this
是指使用.call()
調用該函數:
var rect = new Rectangle(3, 4);
width = 7; // Set in the global scope.
height = 10; // Set in the global scope.
console.log(calcArea.call(rect));
則輸出12
(因爲this
現指rect
對象,而不是全球範圍)。
您可能不希望每次使用calcArea()
都需要這樣做。
爲什麼代碼1不是最佳
代碼1將工作,但並不是最佳的解決方案,因爲每次創建新Rectangle
對象時,它會創建一個calcArea
的屬性,對象是一個不同的功能任何其他Rectangle
對象的任何calcArea
屬性。
你可以看到這一點,如果你這樣做:
function Rectangle(height, width) {
this.height = height;
this.width = width;
this.calcArea = function() { // why use this here?
return this.height * this.width;
};
}
var r1 = new Rectangle(3, 4),
r2 = new Rectangle(6, 7);
console.log(r1.calcArea.toString() === r2.calcArea.toString()); // Line 1
console.log(r1.calcArea === r2.calcArea); // Line 2
將輸出true
測試的功能字符串表示的時候是相同的,但false
測試功能是否相同的時候。
這是什麼意思?如果您創建了1萬個Rectangle
實例,那麼您將擁有10,000個不同的calcArea
屬性實例,並且每個副本都需要額外的內存(外加時間分配內存並在末尾垃圾收集)。
什麼是更好的做法?
function Rectangle(height, width) {
this.setHeight(height);
this.setWidth(width);
}
Rectangle.prototype.setHeight = function(height){ this.height = height; }
Rectangle.prototype.setWidth = function(width ){ this.width = width; }
Rectangle.prototype.calcArea = function(){ return this.height * this.width; }
然後,如果你這樣做:
var r1 = new Rectangle(3, 4),
r2 = new Rectangle(6, 7);
console.log(r1.calcArea.toString() === r2.calcArea.toString()); // Line 1
console.log(r1.calcArea === r2.calcArea); // Line 2
它將返回true
兩個 - 這意味着r1.calcArea
和r2.calcArea
指的是相同的功能,不管有多少實例的Rectangle
有。
在第一個片段中,'calcArea'是'new Rectangle()'創建的'Rectangle'的一個屬性。在第二個片段中,'calcArea'是一個全局變量。 –
@ChrisMartin我們如何確保它是全球性的? – thefourtheye
閱讀https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals,特別是「聲明變量」部分。 –