【问题标题】:Stoyan Stefanov: JavaScript Patterns - Callbacks and ScopeStoyan Stefanov:JavaScript 模式 - 回调和范围
【发布时间】:2014-02-05 16:33:43
【问题描述】:

在“回调和范围”部分的第 4 章(函数)中,您可以找到以下示例:

var myapp = {};
myapp.color = "green";
myapp.paint = function (node) {
    node.style.color = this.color;
};

var findNodes = function (callback) {
    // ...
    if (typeof callback === "function") {
        callback(found);
    }
    // ...
};

在我的这本(电子)书的版本中,作者写道:

"如果你调用 findNodes(myapp.paint),它不会按预期工作,因为 this.color 不会被定义。对象 this 将引用全局对象,因为 findNodes() 作为函数调用,不是作为方法。如果 findNodes() 被定义为名为 dom 的对象的方法(如 dom.findNodes()),那么回调内部的 this 将引用 dom 而不是预期的 myapp。"

我不明白这个解释。可能是作者错了?

在我看来,这种论证具有误导性。如果 findeNotes() 作为方法调用或作为函数调用,则与方法 myapp.paint() 中的 this 值无关。在任何一种情况下,this-value 都将引用全局对象,因为它是由调用“callback(found)”的形式确定的(参见http://dmitrysoshnikov.com/ecmascript/javascript-the-core/#this-value)。

谁能帮我找到正确的答案?

【问题讨论】:

    标签: javascript design-patterns callback this


    【解决方案1】:

    你的想法是正确的。 thisfindNodes 将是全局对象或另一个对象,但 thiscallback 将始终是全局对象。

    一种补救方法是:

    var findNodes = function (callback) {
        // ...
        if (typeof callback === "function") {
            callback.call(this,found); // CHANGED HERE
        }
        // ...
    };
    

    这样,findNodes 的范围将被传递给回调。这至少会使作者正确。

    处理回调更常见的方法是提供一个可选参数来定义范围:

    var findNodes = function (callback, scope) {
        // ...
        if (typeof callback === "function") {
            callback.call(scope,found); // CHANGED HERE
        }
        // ...
    };
    

    【讨论】:

      【解决方案2】:

      作者错了。他可能在解释中误用了findNodespaint

      • 调用 myapp.paint() 将 this 绑定到 myapp 对象
      • 调用 var func = myapp.paint; func() 将此绑定到全局窗口对象。

      修正后的解释可能是这样的

      如果你调用 findNodes(myapp.paint),它不会像预期的那样工作, 因为 this.color 不会被定义。 this 将引用的对象 全局对象,因为 paint() 是作为函数调用的,而不是作为 方法。如果 paint() 被定义为一个名为 dom 的对象的方法 (如 dom.paint()),那么回调内部的 this 将引用 dom 而不是预期的 myapp。

      【讨论】:

      • 感谢您的回答!我还试图“修复”作者的论点。除了最后一句话,您的更正解释对我来说更有意义。为什么paint()应该是dom的方法?
      • 是的,这对我来说也没有意义。 @Tibos 的回答更准确。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-01-11
      • 2015-02-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-22
      相关资源
      最近更新 更多