【问题标题】:JavaScript and jQuery, "this" inside an anonymos functionJavaScript 和 jQuery,匿名函数中的“this”
【发布时间】:2012-05-10 17:28:16
【问题描述】:

我有这个代码:

PageList: function(url, index, classes){
    this.url = url;
    this.index = index;
    ...
};

PageList.prototype.toHTML = function(){
    var div = $('<div class="container"></div>');
    var p = $('<p></p>');
    var link = $('<a></a>');
    $.each(this.elements, function(index, array_value){
          console.log(this.url);
          ...
    }
}

它按预期工作。

问题是console.log(this.url) 正在打印undefined,所以我重新编写了代码,如下所示:

PageList.prototype.toHTML = function(){
    var div = $('<div class="container"></div>');
    var p = $('<p></p>');
    var link = $('<a></a>');
    var instance = this;
    $.each(this.elements, function(index, array_value){
               console.log(instance.url);
        }
}

我知道问题在于闭包没有将 this 作为实例的值,但据我所知,在没有绑定实例的函数内必须引用 this引用 window 对象,而不是 undefined,至少在许多浏览器上都是这样。

那么我的代码到底发生了什么。

注意:我使用的是 jQuery,this.elements 已经定义。

编辑:现在我发现$.each 是一个非实例函数,所以我的回调是从$.each 调用的,但它必须是windowthis 的引用,还在考虑它。

【问题讨论】:

  • 欢迎来到 JavaScript 作用域的世界。

标签: javascript closures this anonymous-function


【解决方案1】:

根据jQuery docs$.each

[当前元素]也可以通过this关键字访问...

在 JavaScript 中,当您将回调函数交给 higher-order function(在本例中为 $.each)时,高阶函数可以决定回调运行时 this 的值。您无法控制这种行为 - 只是不要使用 this(例如,在您的示例中使用 instance 之类的引用或通过闭包)。

查看上下文设置函数 Function.callFunction.apply 以了解像 $.each 这样的高阶函数如何设置回调的 this 上下文。一旦你阅读了那些 MDN 页面,它可能会弄清楚一些事情。

这是一个简单的例子:

Array.prototype.forEachWithContext(callback, this_in_callback) {
    for(var i = 0; i < this.length; ++i) {
        callback.call(this_in_callback, i, this[i]);
    }
}

并使用它:

PageList.prototype.toHTML = function(){
    //...
    this.elements.forEachWithCallback(function(index, array_value){ ... }, this);
}

我的示例Array.forEachWithContext 类似于Array.forEach。但是,它需要一个回调第二个参数,该参数在执行每个回调期间用作this 的值。

【讨论】:

  • 我知道如何使用调用和应用,只是编写这样的代码会很尴尬: $.each.apply(this, ... );个人我不喜欢像这样在同一个命令上混合 jquery 和 js。
  • 你不需要使用我的代码——我只是解释了 jQuery 如何使用call 来改变你的回调的上下文。在这种情况下,$.each 是完全可用的;只需使用您已经拥有的instance 代码。既然您知道call/apply,我的答案的主要价值是jQuery 文档的初始引用:$.each 回调中,this 设置为当前数组元素 .我想这就是你想要的解释。
  • 你说得对,我在控制台上看到了一个“对象”,并认为它指的是窗口对象。
【解决方案2】:

尝试使用$.proxy 包装您的$.each 函数...

$.each(this.elements, $.proxy(function(index, array_value){
    console.log(this.url);
},this));

$.proxy 将确保 this 引用您的 PageList...

【讨论】:

  • 投票支持代理功能,但仍然不知道是什么原因导致它的行为如此。
【解决方案3】:

我知道问题在于闭包没有将 this 作为实例的值,但据我所知,在没有绑定实例的函数内部对 this 的引用必须引用窗口object,而不是 undefined,至少在许多浏览器上都是这样。

this window。您正在打印 window.url,这是未定义的。试试console.log(this),它应该会产生window

【讨论】:

  • 以前没有注意到这一点真是令人尴尬。
  • 等等,这是正确的吗?我的直觉(和测试)表明thisPageList.toHTML 内部时应该等于PageList 实例,然后在$.each 的回调内部等于当前列表元素。你什么时候观察到它在这段代码中等于window,除了PageList之外?
  • 我刚刚阅读了@apsillers 的回答,他可能是对的。但是您的代码中的this.elements 是什么?
  • 所以我猜@apsillers 是对的。我在回答之前浏览了文档,没有看到它,并假设只有.each(而不是jQuery.each)表现得那样。无论如何,我猜elements 数组上的所有值都没有url 属性,因此您的undefined 值。
  • 他们没有 url 属性,url 属于 PageList 实例,这是我的第一个意图,访问外部 this.url。
猜你喜欢
  • 1970-01-01
  • 2012-03-22
  • 1970-01-01
  • 1970-01-01
  • 2014-11-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多