【问题标题】:Correct way of Caching and this when using jQuery正确的缓存方式和使用 jQuery 时的 this
【发布时间】:2017-01-11 15:37:55
【问题描述】:

在使用jQuery的时候,缓存很重要,好像忘记了相关的原理。当我缓存某些东西时,如何在函数on() 中重新使用它?

例子:

var paginationDemo = $("#pagination-demo");
paginationDemo.on('click', function() {
  var index = $('#pagination-demo').find('.active > a')[0].innerHTML;
  ...
});

正如你在这里看到的,我再次调用 jQuery 来查找 id,真丢脸!有没有办法用this 做到这一点?

var index = this.find('.active > a')[0].innerHTML;

或:

var index = $(this).find('.active > a')[0].innerHTML;

但我不确定this 会在on() 的主体中包含什么。这样做的正确方法是什么?

【问题讨论】:

  • this 是 DOM 对象,$(this) 是 jQuery 对象,所以 this.id 和 $(this).find - 但为什么不是 $(this).find('.active > a').html();
  • 那么this 在未命名函数体内会是什么(我们如何调用这些函数?:))?直觉上它将是paginationDemo 变量?所以你的意思是this.id.find() 将等同于$(this).find()
  • 没有。 this.id 和 $(this).attr("id)" 是等价的。忽略这个例子

标签: javascript jquery html function caching


【解决方案1】:

要使用变量缓存,只需在“on”中再次重用变量“paginationDemo”。在这种情况下,第二种方法也可以正常工作。

var index = $(this).find('.active > a')[0].innerHTML;

因为 'this' 仍然持有对 DOM 对象的引用。

但是这种方法在嵌套函数或匿名函数(“未命名”函数)中失去了有效性。因此,您可以保存对该变量的引用以使其正常工作(self 方法)。或者直接使用缓存的变量(paginationDemo)。例如下面:

 var paginationDemo = $("#paginationDemo");
    paginationDemo.on('click', function(e) {
          var self =this;      // saving reference to this
          console.log(this);     // refers to DOM object paginationDemo

          var index = $(this).find('.active > a')[0].innerHTML; 
                                 //will work
          var index = paginationDemo.find('.active > a')[0].innerHTML; 
                                    //will work, this is caching approach

         (function (){
              //inside anonymous fun, this changed now
            console.log(this);      // this refers to "window" object now!
            var index = $(this).find('.active > a')[0].innerHTML; //won't work

            var index = $(self).find('.active > a')[0].innerHTML; 
                               //works !! lexical scope variable self used    

            paginationDemo.find('.to-be-found').text('FOUND');
                                 //works too

       })();
    });

这是一个如何工作的链接: this - JavaScript | MDN

【讨论】:

  • Promil 谢谢!我也在考虑这种方法......也许我在处理函数时必须刷新变量范围......我的意思是匿名函数到底是如何知道self的?你将它声明为var self,因此它不是全球性的......但我相信你!
  • @gsamaras 欢迎 :) Javascript 使用词法范围。 (函数级别范围)因此内部匿名函数可以访问父变量(即变量 self )以及全局对象变量(大多数情况下为窗口)。只是自我=这个; (没有 var)会使其成为全局变量。
  • 那么 self 在匿名函数中会发生什么,与 paginationDemo 发生的事情是一样的,对吧? :) 我从这个问题中学到了很多东西,但是它被正分毁了,我没有得到苏格拉底徽章! ://
  • 哈哈...是的,它们都是全局的,在这里保持不变。 'this' 是一个非常特殊的 js 变量,它在函数中的值取决于调用该函数的人。 (每个函数都有它自己的这个。详细阅读它。非常棒的概念!)
  • 同样从我相信的 ECMA 6 开始,我们可以使用“胖箭头函数”,它根据定义的块而不是调用它的对象来获取“this”的值功能。所以以后不需要分配 self = this :) exploringjs.com/es6/ch_arrow-functions.html
【解决方案2】:

您的第二个选项将起作用:

var index = $(this).find('.active > a')[0].innerHTML;

【讨论】:

  • 感谢您的回答,但我不希望只是这样,我想了解。请参阅我的问题下的评论讨论并尝试扩展您的答案,解释为什么这是正确的方法等,请。 :)
  • 没有$()this是DOM对象,不是jquery对象,DOM对象没有find方法
【解决方案3】:

据我了解,您还想使用您在通过on 注册的回调中创建的 jquery 对象。

来自official docs

除了事件对象,事件处理函数还有 访问处理程序绑定到的 DOM 元素 关键字this。将 DOM 元素转换为 jQuery 对象,我们可以 使用 jQuery 方法,我们只需执行 $( this )

但在这种情况下,您也必须再次构造 jQuery 对象。不像使用选择器来查找元素那么昂贵,但仍然如此。

问题的一个解决方案可能是使用event.data 属性

var paginationDemo = $("#pagination-demo");
paginationDemo.on('click',{ cachedElement:paginationDemo},function(event) {
  var index = event.data.cachedElement.find('.active > a')[0].innerHTML;
  ...
});

通过这种方式,您可以重用原始 jQuery 对象并从缓存中获得您想要的结果。

更新:

在传递给on 的回调中,关键字this 指的是底层DOM 对象。当我们使用这个习惯用法时:$(this) 我们正在构造一个新的 jQuery 对象。但是它与存储在paginationDemo 变量中的jQuery 对象不同。换句话说,两个 jQuery 对象都将作用于同一个 DOM 元素。但是他们的参考是不同的

event.data.cachedElement === $(this)
>false

【讨论】:

  • 方法也不错,+1!但是这种方法和this 有什么区别呢?它们是等价的吗?
  • 回调中的this关键字实际上是指底层的DOM对象。现在,如果我们执行 $(this),我们基本上就是将 DOM 对象包装在一个 jQuery 对象中。但是 jQuery 对象是重新创建的。它不是对存储在 paginationDemo 中的对象的引用。换句话说, paginationDemo 和 $(this) 都会作用于同一个 DOM 元素,但实际上是不同的对象。
  • 我没有看到你的代码的必要性。这也应该有效:var $paginationDemo = $("#pagination-demo"); $paginationDemo.on('click',function() { var index = $(this).find('.active > a').text(); }); 假设 `10' - 文档在哪里说 $(this) 是新副本?
  • 就像我在答案中所说的,一般习惯用法是使用 $(this).... 我只是在建议我想到的替代方案:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-06
  • 2022-11-02
  • 2023-04-09
  • 2011-04-16
相关资源
最近更新 更多