【问题标题】:Javascript Revealing Module Pattern - this and internal function callsJavascript Revealing Module Pattern - this 和内部函数调用
【发布时间】:2013-09-19 09:11:57
【问题描述】:

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

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()pri() 时,this 指的是vm 的当前实例。但是,当我从pub() 中调用pri() 时,突然this 已恢复为引用全局窗口对象。我认为揭示模块模式的目标之一是消除this 的问题,但似乎在从另一个函数中调用一个函数时,我失去了this 的值。

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

【问题讨论】:

  • 没有。显示模块模式的目标始终是且仅是提供私有范围。顺便说一句,您甚至不使用 RMP,而是使用构造方法(尽管当您明确地 return 处理对象时,new 没有帮助)。

标签: javascript revealing-module-pattern


【解决方案1】:

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

构造函数调用

var it = new vm();

functionvm 内部,this 指的是您要返回的对象实例。这是意料之中的。

方法调用

it.pub();

functionpub 内部,这指的是it 引用的对象实例相同的对象实例。同样,这是意料之中的。

函数调用

pri();

functionpri 内部,this 指的是全局对象。这不是预期的,并且被认为是 JavaScript 语言中的错误。 'pub' 函数是使用方法调用模式调用的,因此很自然地假设 this 在其中使用时应该始终指向当前函数/对象。

一种补救方法是将返回的对象存储在 vm 方法内的局部变量中,然后由于作用域,pubpri 方法将能够安全地引用对象实例。

function vm() {
    var pub = function () {
        alert("from pub: " + that);
        pri();
    },
    pri = function () {
        alert("from pri: " + that);
    };

    var that = {
        pub: pub,
        pri: pri
    };

    return that;
}

【讨论】:

  • 感谢您 - 我已经找到了解决我在真实代码中看到的问题的方法,尽管我确实喜欢您处理它的方式。我想我正在阅读的关于揭示模块模式的信息略微夸大了它在清除“this”问题方面的有效性。
【解决方案2】:

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

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

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

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

【讨论】:

    【解决方案3】:

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

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多