2013-12-14 142 views
0

比較代碼1和代碼2,哪一個是正確的?爲什麼在構造函數中使用這個關鍵字

function Rectangle(height, width) { 
    this.height = height; 
    this.width = width; 
    this.calcArea = function() { // why use this here? 
     return this.height * this.width; 
    }; 

} 

碼2 我認爲它的罰款與此:

function Rectangle(height, width) { 
     this.height = height; 
     this.width = width; 
     calcArea = function() { 
      return this.height * this.width; 
     }; 

    } 
+2

在第一個片段中,'calcArea'是'new Rectangle()'創建的'Rectangle'的一個屬性。在第二個片段中,'calcArea'是一個全局變量。 –

+0

@ChrisMartin我們如何確保它是全球性的? – thefourtheye

+0

閱讀https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Values,_variables,_and_literals,特別是「聲明變量」部分。 –

回答

1

如果你不使用thiscalcArea將無法​​通過矩形的對象訪問。當你說,

this.calcArea = function() ... 

創建在當前對象(this)和功能的新變量將被分配給它,從而使該對象將有機會獲得它。

試試看這些陳述,有無this。你會更好地理解。

var a = new Rectangle(1, 2); 
console.log(a.calcArea()); 
+0

使用'this.calcArea = function()...'將創建一個屬於類「Rectangle」類的實例 - 所以如果你創建了10,000個「Rectangle」實例,那麼你還將創建10,000個「calcArea」實例'功能。我們應該做的是將成員函數附加到類的原型 - 例如:function Rectangle(w,h){this.setWidth(w); this.setHeight(H);}; Rectangle.prototype.setWidth = function(w){this.width = w;}; Rectangle.prototype.setHeight = function(h){this.height = h;}; Rectangle.prototype.calcArea = function(){return this.width * this.height;};' – MT0

+0

@ MT0 OP只是想知道爲什麼'this'在那裏被使用。 – thefourtheye

+0

OP想知道「哪一個是正確的?」 – MT0

0

第二個版本將設置全局變量calcArea,以便在構造對象的實例時爲對象執行特定的操作。需要使用此設置來設置特定對象的屬性。

0

當你序言的方法和屬性與「本」在你的構造,他們允許獲得與構造函數使用這些屬性和方法,並將這些屬性和方法新創建的對象創建的新對象。

如果您創建一個基於你不使用「這個」作爲序言油杉,並期待在鉻調試器您會收到以下錯誤矩形構造的版本,一個新的對象:

Object #<Rectangle> has no method 'calcArea' 

總之它根本不被認可。

不使用「this」的其他方面是該方法變成'全局'。

這裏是一個代碼示例演示:

function Rectangle(height, width) { 
    this.height = height; 
    this.width = width; 
    calcArea = function() { // Not prefaced with 'this' 
     return 'hello world'; 
    }; 

} 


var aNewObj = new Rectangle(10,10); 

console.log(calcArea()) // Notice this is not aNewObj.calcArea() ...just calcArea() but its still accessible. 
1

which one is correct?

這取決於你如何看待 「正確」:

  • 要麼聲明不能被正確解析?
    • 不,這兩個都是有效的JavaScript。
  • 哪一個會計算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());

將輸出NaNcalcArea在全球範圍內的一部分,所以沒有一個Rectangle類的任何實例的知識和全球範圍內不具有heightwidth屬性。

如果我們這樣做:

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.calcArear2.calcArea指的是相同的功能,不管有多少實例的Rectangle有。

+0

內存管理! thx這麼多提示! – user3057928

相關問題