【问题标题】:Why doesn't passing that.method as a parameter work?为什么不将 that.method 作为参数传递?
【发布时间】:2014-04-12 19:58:32
【问题描述】:

在代表请求的类中,我尝试使用 Q Promise 处理它,然后使用两个简单的处理程序来发送处理结果。为什么这不起作用:

Request.prototype.process = function() {
    var that = this;
    return that.getParameter('method')
    .then(function(method) {
        // ... Some processing
    })
    .then(that.replyOK)
    .fail(that.replyError);
};

但这确实:

Request.prototype.process = function() {
    var that = this;
    return that.getParameter('method')
    .then(function(method) {
        // ... Some processing
    })
    .then(function(error) {
        that.replyOK(error);
    })
    .fail(function(error) {
        that.replyError(error);
    });
};

【问题讨论】:

  • 可能是因为您的 replyOKreplyError 函数关心 this 在其体内的内容,这不像您认为在第一种情况下的使用那样受到约束,而在第二个。
  • 你确定第二个例子中有.then(...).fail(...) 之前的分号吗?
  • 正如 Bray 所说,在第一种情况下,replyOKreplyError 中的 this 未在调用中设置,因此它将默认为全局对象(或在严格模式下保持未定义),但在第二种情况下设置为 that
  • 如果that.replyOK 有效,那么您根本不需要that 变量。
  • Golergka,是的,确实每个人都有自己的想法。容忍new 的缺失确实是lib' 作者应该考虑的问题(文章的作者John Resig 是jQuery 的创建者)。在您自己的代码中,当调用您自己的 ad hoc 构造函数时,与 lib' 使用者相比,您忘记new 的可能性要小得多,但 Resig 的方法肯定会保留在您的工具箱中.

标签: javascript node.js promise q


【解决方案1】:

JavaScript 主要是词法范围的。这意味着在:

 function foo(){
     var that = this;
     //...
 }

在 foo that 的以下行中访问该变量的变量设置为您所期望的。如果您通过在其他地方定义的局部变量传递函数,that 将不会在其词法(变量)环境中被捕获。

JavaScript 也有动态的this,方法的this 由当前调用的对象决定。例如:

var a = {
           x:3,
           getX:function(){ return this.x; }
        };
var b = {x:5};
b.getX = a.getX;
b.getX(); // returns 5
a.getX(); // returns 3
a.getX.call(b); // set `this` explicitly with .call, returns 5
var x = a.getX;
x(); // global x or undefined.

可以像这样使用Function.prototype.bind 固定this

Request.prototype.process = function() {
    return this.getParameter('method')
    .then(function(method) {
        // ... Some processing
    })
    .then(this.replyOK.bind(this))
    .fail(this.replyError.bind(this));
};

或者,在 EcmaScript 6 语法中(节点中尚不可用,但很快):

Request.prototype.process = () => { // arrow functions have lexical `this` 
    return that.getParameter('method')
    .then(function(method) {
        // ... Some processing
    })
    .then(this.replyOK)
    .fail(this.replyError);
};

【讨论】:

  • 感谢您的回答!但是,我不太明白这句话:“如果你通过在别处定义的局部变量传递函数,那将不会在它们的词法(变量)环境中被捕获。”你确定你说的是“那个”而不是“这个”吗?因为如果不捕获“那个”,那么这些都不会起作用。
  • @golergka 只有 closure 被捕获。例如,function a(){ alert(that.foo); }; function b(){ this.foo = "Bar"; var that = this; a();}不能在 JavaScript 中工作,但可以在具有动态作用域的语言(如 Perl)中工作。见ericlippert.com/2013/05/20/what-is-lexical-scoping
  • 感谢 Eric 博客的链接!作为来自 C# 的人,我发现它最有用:)
  • @golergka 我看到了,这就是我推荐那篇文章的原因:) 这也是一本很棒的书。很高兴我能帮上忙。
  • 是的,因为 replyOK 是在别处定义的。 replyOk 和 replyError 必须使用 => 自己创建
猜你喜欢
  • 2023-03-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-09
  • 2016-08-16
  • 1970-01-01
  • 2011-10-27
相关资源
最近更新 更多