2

我最近一直在我的 Javascript 中使用Revealing Module 模式来帮助构建我的代码,并且一切都很顺利。但是,我对这段代码有点困惑:

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();

JSFiddle

当我直接调用pub()and时pri()this指的是vm. 但是,当我pri()从内部调用时pub()突然this又恢复到引用全局窗口对象。我认为揭示模块模式的目标之一是消除问题,this但似乎当从另一个函数中调用一个函数时,我失去了this.

有谁知道为什么会这样,如果有办法让它工作而不必传递对当前对象的引用?

4

3 回答 3

8

您的示例结合了调用函数的四种方式中的三种。

构造函数调用

var it = new vm();

里面的function vm,this指的是你要返回的对象实例。这是意料之中的。

方法调用

it.pub();

在 内部function pub, this 指的是与 所引用的对象实例相同的对象实例it。同样,这是意料之中的。

函数调用

pri();

里面的function prithis指的是全局对象。这不是预期的,并且被认为是 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;
}
于 2013-09-26T19:38:05.497 回答
1

调用pri()Insidepub实际上调用了范围内的捕获pri变量。在没有目标对象的情况下这样调用它将设置this为全局(窗口)对象。

您可能想了解thisJavascript 的工作原理,因为它与您可能知道的其他面向对象语言非常不同。this是动态的,并且会根据您调用方法的方式而变化。

在您的情况下,修复很容易:像这样调用函数:this.pri(). 这将正确调用pri当前this对象的成员(即var it),并将其this设置为this... 如果这句话有意义!

this.永远不要认为您可以在 javascript 代码中省略,就像在 C# 或 Java 中一样。

于 2013-09-26T19:46:13.457 回答
0

正如其他人所解释的那样,我只是为您提供一种技术,以使您的上下文紧贴您的对象。您可以使用bind当前上下文来收紧您的对象。注意,并非所有浏览器都支持它(旧版本的 IE 失败)。除了技术有爱好者和反对者。

return {
  pub: pub.bind(this),
  pri: pri.bind(this)
};

http://jsfiddle.net/zreFY/1/

于 2013-09-26T20:06:58.177 回答