我最近在我的Javascript中使用Revealing Module pattern来帮助构建我的代码并且一切都很顺利。但是,我对此代码段感到有点困惑:
function vm() {
var pub = function () {
alert("from pub: " + this);
pri();
},
pri = function () {
alert("from pri: " + this);
};
return {
pub: pub,
pri: pri
};
}
var it = new vm();
it.pub();
it.pri();
当我直接致电pub()
和pri()
时,this
会引用vm
的当前实例。但是,当我从pri()
内调用pub()
时this
突然this
已恢复为引用全局窗口对象。我认为揭示模块模式的目标之一是删除this
的问题但似乎从另一个函数中调用函数时我失去了{{1}}的值。
有没有人知道为什么会这样,如果有办法让它工作而不必传递对当前对象的引用?
答案 0 :(得分:8)
您的示例结合了调用函数的四种方法中的三种。
var it = new vm();
在function
vm
内,this
指的是您要返回的对象实例。这是预期的。
it.pub();
在function
pub
内部,这指的是与it
引用的对象实例相同的对象实例。再次,这是预期的。
pri();
在function
pri
内,this
指的是全局对象。这不是预期的,并且被认为是JavaScript语言中的错误。使用方法调用模式调用'pub'函数,因此很自然地假设this
在内部使用时应始终指向当前函数/对象。
一种补救方法是将返回的对象存储在vm方法内的局部变量中,然后由于作用域,pub
和pri
方法将能够安全地引用对象实例。
function vm() {
var pub = function () {
alert("from pub: " + that);
pri();
},
pri = function () {
alert("from pri: " + that);
};
var that = {
pub: pub,
pri: pri
};
return that;
}
答案 1 :(得分:1)
在pri()
内调用pub
实际上会调用范围内的已捕获pri
变量。在没有目标对象的情况下调用它会将this
设置为全局(窗口)对象。
您可能想了解this
在Javascript中的工作原理,因为它与您可能知道的其他面向对象语言非常不同。 this
是动态的,并根据您调用方法的方式而变化。
在您的情况下,修复很容易:调用函数:this.pri()
。这将正确调用当前pri
对象的this
成员(即var it
),this
设为this
...如果此句话为感!
永远不要认为你可以在javascript代码中省略this.
,就像在C#或Java中一样。
答案 2 :(得分:0)
正如其他人对它的解释一样,我只是为您提供一种技巧,以保持您的背景紧密。您可以使用bind
来锁定当前上下文的对象。注意,并非所有浏览器都支持它(旧版本的IE失败)。除了技术有爱好者和反对者。
return {
pub: pub.bind(this),
pri: pri.bind(this)
};
<强> http://jsfiddle.net/zreFY/1/ 强>