为什么在构造函数函数中使用此关键字
why use this keyword in constructor function
比较代码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;
};
}
哪一个是正确的?
这取决于您如何看待"正确":
- 两个声明中的任何一个都无法正确解析吗?
- 不,两者都是有效的JavaScript
- 哪个将计算
calcArea
?- 代码1将正确地计算它,而代码2不会创建
Rectangle
类的成员函数,但您可以使它正确地计算,并在广告重定向方面遇到一些困难。请参见下文
- 代码1将正确地计算它,而代码2不会创建
- 创建类的一个好方法是什么?
- 不,他们都没有。请参见底部
代码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
对象)。
如果我们使用.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
属性,该属性与任何其他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
。
这是什么意思?如果您创建了10000个Rectangle
实例,那么您也将有10000个不同的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
有多少实例。
如果不使用this
,则无法通过Rectangle的对象访问calcArea
。当你说
this.calcArea = function () ...
在当前对象(this
)中创建一个新变量,函数将被分配给它,这样对象就可以访问它。
尝试以下语句,无论是否使用this
。你会更好地理解的。
var a = new Rectangle(1, 2);
console.log(a.calcArea());
第二个版本将设置全局变量calcArea,以便在构建对象实例时执行特定于对象的操作。设置特定对象的属性时需要使用此选项。
当您在构造函数中为方法和属性加上"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.
- ES6构造函数返回基类的实例
- 使用Google Visualization动态调用构造函数
- javascript中对象构造函数中的var属性与this.properties
- 理解typescript中的构造函数接口
- 为什么构造函数不是构造函数
- 如果在构造函数中有“返回”,则在 JavaScript 中的新运算符中做了什么
- 拦截对构造函数的调用
- 使用闭包共享构造函数参数
- 文本表示法VS.构造函数,用于在JavaScript中创建对象
- 从js引擎的角度来看闭包和构造函数是如何工作的
- 如何使用此从对象访问构造函数
- 为什么在构造函数函数中使用此关键字
- 正在检测是否在构造函数内部使用了新关键字
- 为什么实例没有't在没有prototype关键字的情况下继承添加到构造函数的属性
- 为什么函数在构造函数中声明时不使用new关键字
- 该关键字是构造函数中的窗口对象
- 从构造函数中引用Javascript实例变量而不使用'this'关键字
- 匿名函数/构造函数中的关键字
- JavaScript:关于构造函数**新**关键字的问题
- return和new关键字构造函数模式的区别是什么?