比较代码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;
};
}
答案 0 :(得分:1)
如果您不使用this
,则无法通过Rectangle对象访问calcArea
。当你说,
this.calcArea = function () ...
在当前对象(this
)中创建一个新变量,并将该函数分配给它,以便该对象可以访问它。
尝试使用和不使用this
的这些语句。你会更好地理解。
var a = new Rectangle(1, 2);
console.log(a.calcArea());
答案 1 :(得分:1)
哪一个是正确的?
这取决于您查看“正确”的方式:
calcArea
?
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
对象。 / p>
如果我们使用.call()
更改this
引用的内容来调用函数:
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
属性,该属性与任何{{1}不同。任何其他calcArea
对象的属性。
如果你这样做,你可以看到:
Rectangle
在测试函数的字符串表示时,输出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
。
这是什么意思?如果您创建10,000个false
实例,那么您将拥有10,000个Rectangle
属性的不同实例,每个副本将需要额外的内存(加上时间分配该内存并在最后垃圾收集它) )。
什么是更好的做法?
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
的实例数是多少。
答案 2 :(得分:0)
第二个版本将设置全局变量calcArea,以便在构造对象的实例时执行特定于对象的内容。设置特定对象的属性需要使用它。
答案 3 :(得分:0)
当你在构造函数中使用'this'作为方法和属性的前言时,它们允许使用该构造函数创建的任何新对象使用这些属性和方法,并使这些属性和方法指向新创造的对象。
如果你根据你的版本的Rectangle构造函数创建一个新对象,它不使用'this'作为calcArea的前言并查看chrome调试器,你会收到以下错误:
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.