问题 JQuery延迟更改“this”


我试图让一个javascript对象运行一个延迟方法,当它的.done()调用同一个对象中的一个函数时。我有问题因为“this”成为延迟对象而不是调用它的对象。

PageObject.prototype.successFunction = function() {
  console.log(arguments);
  return console.log(this.name + " Success function called");
};

PageObject.prototype.loadPage = function(url) {
  return $.when($.mobile.loadPage("pages/" + url))
    .done(this.successFunction);
};

var pg = new PageObject();
pg.loadPage("test.html");

如何将“this”发送到successFunction?这个PageObject也将被其他人扩展,因此在运行successFunction时知道“this”将非常方便。

这似乎很简单,可能有一个简单的答案。我正在研究.apply(),但我不确定它是否有帮助。关于堆栈溢出的这篇文章有点帮助,但它把它放入.done()函数的那一刻就打破了。

函数作为参数(带参数) - JavaScript


8618
2017-09-06 01:35


起源

FWIW,延迟对象不会改变它,它只是函数的工作方式。它的值不是由定义函数的方式/位置决定的,而是由它的调用方式决定的。 - Felix Kling


答案:


jQuery的 proxy 将返回绑定到特定上下文的函数:

PageObject.prototype.loadPage = function(url) {
  return $.when($.mobile.loadPage("pages/" + url))
    .done($.proxy(this.successFunction, this));
};

还有ES5 bind 其操作类似但需要在旧浏览器中填充

PageObject.prototype.loadPage = function(url) {
  return $.when($.mobile.loadPage("pages/" + url))
    .done(this.successFunction.bind(this));
};

apply 和 call 可以使用指定的上下文立即执行函数,但是 proxy 和 bind 返回一个可以在以后使用或传递给其他函数的函数。


14
2017-09-06 01:40



很棒的答案,这正是我所需要的(而且我疯狂地试图解决它)。我最终使用你发布的$ .proxy版本。谢谢! - Chris


this JavaScript中的“变量”称为“调用对象”,并在调用其封闭函数时确定(而不是在定义时)。它可以设置几种不同的方式:

  1. 你可以使用它来设置它 . 运算符(例如 myObject.myFunction()
  2. 您可以使用函数设置它 call() 要么 apply() 方法
  3. 您可以(在ES5下)使用函数永久绑定它 bind() 方法
  4. 如果上述方法都没有将其设置为其他方法,则它将默认为全局对象

要理解的重要一点是(除了上面的方法3之外),所有关于函数在被调用时如何被调用,而不是如何被引用,而不是如何被存储,而不是它被创建的位置。

在你的情况下,你正在路过 this.successFunction 作为jQuery调用的函数引用,但它并没有这样调用它(因为它只是对函数的引用,而不是关于如何调用该函数的任何信息)。

你可以使用jQuery的一些奇特的技巧 $.proxy() 或ES5的 .bind() 方法,但归根结底,处理它的最直接的方法是简单地保留 this 通过一个闭包范围的变量并使用一个函数包装器:

PageObject.prototype.loadPage = function(url) {
    var self = this;
    return $.when($.mobile.loadPage("pages/" + url))
            .done(function () { self.successFunction(); });
};

请注意,我们使用方法1来显式绑定 successFunction调用对象与loadPage的调用对象相同。它简短,简单,清晰,在ES3下运行良好,并且不依赖于jQuery。


2
2017-09-06 03:06



对于幕后发生的事情+1,但我倾向于喜欢花哨的技巧,如果可用的话,因为它可以使代码更清晰。 - Dennis