【问题标题】:Why and how does jQuery's `$(this)` reference the right nodes?jQuery 的 `$(this)` 为什么以及如何引用正确的节点?
【发布时间】:2012-06-14 14:50:39
【问题描述】:

我知道如何使用 jQuery 的$(this) 选择器,也了解 Javascript 中的 OOP 原理。我一直认为它只是有效,因为其他人实现了它,但我很想知道它为什么以及如何有效。

$(function(){
   $('.foo').each(function(){
      console.log($(this));
   });
});

鉴于此代码。我知道$('.foo') 找到一组 HTML 元素并返回一个 jQuery 对象,该对象能够使用 .each(...) 对其进行迭代。 each() 方法的内部结构然后可能会调用已作为参数传递的闭包。

但是为什么this 会引用闭包内的特定 HTML 元素呢?我一直认为this 只会引用一个新范围,只要它的包装器是使用new 实例化的。那么如果this 引用window 会不会更加一致?

【问题讨论】:

  • this 在 javascript 中很奇怪。搜索网络,你会发现很多人解释它的博客文章

标签: javascript jquery this internals


【解决方案1】:

最后,您始终可以使用.call.apply 在函数中强制设置this 值。 jQuery 这样做;看source of .each

if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
//                  ^ `this` value

在这里,this 值将设置为元素 (object[i]),计数器 (i) 和元素作为参数传递给您的函数,即 callback

【讨论】:

  • 我知道.call() 的存在,但我没想到将它与作为HTML 元素的参数结合使用。我想不出更好的答案,这很好地解释了它。谢谢!
  • @YMMD:实际上它与您可以传递给.call 的其他任何东西并没有太大区别。如果您传递包含元素的变量,则该元素将是 this 值。
【解决方案2】:

“为什么”是因为jQuery(selector).each定义 来操作的:

...回调是在当前 DOM 元素的上下文中触发的,所以关键字 this 指的是元素。

不需要这样做,但确实如此。 (有关“如何”使用的机制,请参阅 Function.callFunction.apply。)

编码愉快!

【讨论】:

  • 如果不是,那么唯一的可能性是将参数传递给引用该元素的回调,还是有其他方法?也感谢您的快速回答!
【解决方案3】:

这是一个简单的迭代所有匹配元素与类.foo 并使用.call/.apply 调用内部函数。

检查.each 实现http://james.padolsey.com/jquery/#v=git&fn=jQuery.each

注意以下代码中的 .call/.apply 调用,确保 this.foo[i]

jQuery.each 实现

function (object, callback, args) {
    var name, i = 0,
        length = object.length,
        isObj = length === undefined || jQuery.isFunction(object);
    if (args) {
        if (isObj) {
            for (name in object) {
                if (callback.apply(object[name], args) === false) {
                    break;
                }
            }
        } else {
            for (; i < length;) {
                if (callback.apply(object[i++], args) === false) {
                    break;
                }
            }
        }
    } else {
        if (isObj) {
            for (name in object) {
                if (callback.call(object[name], name, object[name]) === false) {
                    break;
                }
            }
        } else {
            for (; i < length;) {
                if (callback.call(object[i], i, object[i++]) === false) {
                    break;
                }
            }
        }
    }
    return object;
}

【讨论】:

    猜你喜欢
    • 2015-02-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多