哪个是正确的?
这取决于你如何看待“正确”:
- 是否会无法正确解析任一声明?
- 哪一个会计算
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()
如果您在代码 2 中创建 Rectangle 的新实例,则:
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 属性,该属性与任何其他 @ 的任何 calcArea 属性不同。 987654354@对象。
如果你这样做,你会看到这个:
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 和r2.calcArea 指的是相同的函数,无论有多少Rectangle 实例。