哪一个是正确的?
这取决于你如何看待“正确”:
- Will either declaration fail to be parse correctly?
- Which one will calculate
calcArea
?
- 代码 1 将正确计算它,代码 2 不会创建该成员函数
Rectangle
类,但你可以让它正确计算,但广告重定向有点困难。见下文。
- Is either one good practice for creating classes?
代码 1 -calcArea()
如果您创建一个新实例Rectangle
在代码1中然后:
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
as calcArea
在全局范围的一部分,因此不知道任何实例Rectangle
类和全局范围没有height
or a 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
(since this
现在指的是rect
对象而不是全局范围)。
您可能不想每次使用时都必须这样做calcArea()
.
为什么代码 1 不是最优的
代码 1 可以工作,但不是最佳解决方案,因为每次创建新的Rectangle
它将创建一个对象calcArea
该对象的属性与任何对象都有不同的功能calcArea
任何其他的属性Rectangle
object.
如果您这样做,您可以看到这一点:
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
测试功能是否相同时。
这是什么意思?如果您创建 10,000 个实例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
and r2.calcArea
引用相同的函数,无论有多少个实例Rectangle
有。