考虑一下:
window.onload = function () {
myObj.init();
};
var myObj = {
init: function () {
console.log("init: Let's call the callMe method...");
//callMe is not defined...
callMe();
//Works fine!
this.callMe();
},
callMe: function () {
console.log('callMe');
}
};
由于init函数以这种方式调用(myObj.init),我希望this
在init函数中是myObj。如果是这种情况,为什么callMe
函数会失败?如何在不使用init主体中的this上下文的情况下调用callMe
函数? (实际上,通过函数一遍又一遍地使用this
来调用对象方法太烦人了。那么拥有单个对象有什么意义呢?)
我想知道如何解决这个问题,以便使用上面代码中的第一个调用来调用callMe方法?
答案 0 :(得分:8)
this
永远不会隐含在JavaScript中,因为它在其他一些语言中也是如此。虽然有办法,但使用with
语句:
init: function () {
console.log("init: Let's call the callMe method...");
// Make `this` implicit (SEE BELOW, not recommended)
with (this) {
// Works
callMe();
}
},
......这通常是一个坏主意。 Douglas Crockford可能写了一个更好的描述为什么这是一个坏主意,你可以找到here。基本上,使用with
几乎不可能告诉代码将要执行的操作(并且如果您在with
语句中执行其他任何,则会减慢代码的速度来自this
对象。)
这不是JavaScript的this
与其他语言不同的唯一方式。在JavaScript中,this
完全由如何调用函数定义,而不是函数定义的。当您执行this.callMe()
(或等效this["callMe"]()
,或当然foo.callMe()
等)时,会发生两个事件:从属性中检索函数引用,并以特殊方式调用函数,将this
设置为属性来自的对象。如果您没有通过该属性调用函数,则调用不会设置任何特定的this
值,并且您将获得默认值(这是全局对象;浏览器上为window
)。这是进行调用以设置this
是什么的行为。我在我的博客here和here上的几篇文章中深入探讨了这一点。
如果您查看所有函数对象上可用的JavaScript call
和apply
函数,则可以使此(无双关语)更清晰。如果我这样做:
callMe.call({});
...它会将callMe
函数调用空白对象({}
)作为this
。
基本上,只需习惯输入this
即可。 :-)使用与对象关联的属性和方法仍然很有用,即使没有隐式this
的语法方便(和混淆!)。
答案 1 :(得分:2)
您还可以使用模块模式,它捕获闭包内的所有私有变量,因此您可以在没有this
,的情况下自由使用它们,因为它们位于相同的范围。然后,您可以选择要公开的方法/变量:
var myObj = (function () {
var init = function () {
callMe(); // This now works
};
var callMe = function () {
...
};
// Now choose your public methods (they can even be renamed):
return {
init: init, // Same name
callMyName: callMe // Different name
};
}) ();
现在:
myObj.init(); // Works
myObj.callMyName(); // Works
myObj.callMe(); // Error