在构造函数中使用“new”,John Resig的#35

时间:2011-03-22 00:31:59

标签: javascript

这是来自John Resig的学习高级JavaScript#35 http://ejohn.org/apps/learn/#35,名为当我们忘记使用new运算符时会发生什么?

所以他告诉我们名字变量(我假设是window.name)被覆盖了,但是

1)是否在函数User内完成覆盖,即this.name为名称设置新的全局值?

2)如何使用“新用户”(即构造函数?)阻止覆盖window.name变量?是因为“新用户”只是User的一个实例,但window.name是全局的吗?

谢谢你能帮忙解释一下。

function User(first, last){ 
  this.name = first + " " + last; 
} 

window.name = "Resig"; 
var user = User("John", name); 

assert( name == "John Resig", "The name variable is accidentally overridden." );

4 个答案:

答案 0 :(得分:4)

User()内调用new会使this在函数内部引用全局对象,即浏览器中的window。因此,将覆盖name对象的window属性。另请注意,user将包含值undefined,因为该函数不会返回值。

如果使用new调用该函数,this将引用一个继承自User.prototype的空对象。 window.name保持不变,而是设置空对象的name属性。该函数也隐式返回了这个新对象,因此user将引用它。

答案 1 :(得分:1)

因为没有使用new,所以代码调用了一个名为User的函数,它将全局对象的name属性设置为与当前值不同的值。这将导致可能难以追踪代码中的错误。至于第2点,你是正确的,因为窗口对象包含'全局'命名空间。

答案 2 :(得分:1)

缺点是:如果您使用newthis指的是新对象。如果您不使用new,则this会引用window

如果未使用this.name,则window.name相当于new

答案 3 :(得分:1)

当使用new运算符调用函数时,其this关键字设置为引用一个新对象,其内部[[prototype]]属性是对构造函数的公共原型的引用。

当函数作为构造函数调用时(即使用new关键字):

  this.name = ...

为该新对象添加名称属性并为其指定一个vaule。此外,默认情况下,该函数会将该新对象返回给调用者。

如果在调用函数时省略new,则其this关键字是对全局对象的引用,因此上面的行将RHS上的值赋给全局对象的name属性。

然而,这是一个非常容易发现的错误,因为函数将返回undefined。一旦应该引用User实例的变量几乎用于任何事情,它就会引发一个难以错过的错误,并可能在那里结束脚本执行。

所以从例子中可以看出:

function User(first, last) {
  this.name = first + " " + last;
}
var fred = User('fred','smith');
alert(fred.name);  // Error: fred is undefined

所以是的,忘记使用new可能是一个问题,但它并不是一个很大的问题因为构造函数没有被广泛使用,模块模式对于大多数事情来说已经足够了。