这是来自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." );
答案 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)
缺点是:如果您使用new
,this
指的是新对象。如果您不使用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可能是一个问题,但它并不是一个很大的问题因为构造函数没有被广泛使用,模块模式对于大多数事情来说已经足够了。