【问题标题】:Javascript function pointers with Jquery causing domManip is not a function error带有 Jquery 的 Javascript 函数指针导致 domManip 不是函数错误
【发布时间】:2011-07-03 18:52:45
【问题描述】:

JQuery 版本

jQuery JavaScript 库 v1.4.4

问题

解决方案可能很明显,但我摸不着头脑。

问题是在进行一些代码优化时,我遇到了一个在 jquery 元素上调用 append 几次的循环,这是一个相当大的循环。所以它看起来像这样:

var list_of_goodies = [1,2,3,...];
$.each(list_of_goodies, function(val) {
      $('div.toaddto').append(val);
      ...some more code...
      $('div.toaddto').append(otherval);
});

正如你所看到的并没有真正优化,所以我尝试使用函数指针,所以它看起来像这样:

var list_of_goodies = [1,2,3,...];
var toaddtoAppend = $('div.toaddto').append;
$.each(list_of_goodies, function(val) {
      ... the other code...
      toaddtoAppend(val).append(otherval);
});

这似乎不是一个巨大的优化,但它是一个很大的列表,这可以节省大量查找时间,尤其是在较旧的 IE 中。 然而,这会导致错误。

错误

this.domManip 不是函数

不幸的是,这是来自缩小的 jQuery,因此没有更多信息,但它似乎发生在 wrapInner() 中。

问题

这是范围问题还是参考问题?我在没有使用 jQuery 的情况下对其进行了测试,并且函数指针有效。

$.each 或 for 循环最终得到相同的结果。有人知道我在这里哪里出错了吗? 我对 javascript 如何处理函数指针知之甚少,尤其是当它们应该与某个事物的实例相关联而不是静态的时,所以请原谅这里的任何无知。

经过测试的浏览器

  • 火狐3.6
  • IE 6、7 和 8
  • Chrome 9.0.something

无论浏览器如何,结果总是相同的,这似乎表明不是浏览器如何处理导致它中断的指针。

自己测试

<html>
   <head>
     <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.4/jquery.min.js"></script>
     <script type="text/javascript">   
         $(function(){
            var iterables = [];
            for (var i = 0; i < 1000; i++) iterables.push(i);
            var divAppend = $('#test').append;
            $.each(iterables, function(val) {
               divAppend(val);               
            });
         });       
      </script>
   </head>
   <body>
      <div id="test"></div>
   </body>
</html>

谢谢, 神经元

【问题讨论】:

    标签: javascript jquery function-pointers


    【解决方案1】:

    当您编写 var divAppend = $('#test').append 时,您存储的是对 jQuery 标准 append 函数的引用。
    相当于写var divAppend = $.fn.append——$('#test') 不存储在任何地方。

    当您将divAppend 作为普通函数调用时,它的thiswindow,而不是jQuery 对象。

    你需要存储一个显式调用$('#test').append(...)的函数,或者使用divAppend.call($('#test'), val)在正确的对象上显式调用append

    【讨论】:

      【解决方案2】:

      当你这样做时:

      var toaddtoAppend = $('div.toaddto').append;
      

      您确实获得了对“追加”函数的引用,但是您失去了与 jQuery 对象的关系。因此,当它稍后被调用时,没有 this 引用可供它使用。

      在较新的浏览器(和 JavaScript 引擎)中有一个函数实例可用的方法称为“绑定”,可以在这里做你想做的事:

      var toaddtoAppend = $('div.toaddto').append.bind($('div.toaddto'));
      

      (当然,我不会这样写,带有冗余调用,但这只是一个说明。)这将为您提供一个调用“append”的函数的引用,this 是对那个 jQuery 对象。

      【讨论】:

      • 这让事情变得更加清晰,我不确定它是否会保持或失去参考。由于我研究过的所有应用和调用都不支持绑定,并发现了一些跨浏览器的不同解决方案。现在看看我是否真的会使用这些来提高性能。谢谢。
      【解决方案3】:

      这是一个范围问题,这将在您调用函数时引用窗口。 您可以将调用包装到另一个函数中并将其存储以供以后使用。

      但是,您真正要防止的不是查找​​函数,而是多次查询 DOM 树。

      您可以将 jQuery 对象与所​​有项目存储在一个变量中并引用它。

      var toaddto = $('div.toaddto');
      $.each(list_of_goodies, function(val) {
            toaddto.append(val);
            ...some more code...
            toaddto.append(otherval);
      });
      

      如果您坚持存储对函数的引用,您也可以这样做:

      var toaddto = $('div.toaddto');
      var myappend = toaddto.append;
      $.each(list_of_goodies, function(val) {
            myappend.call(tooaddto,  val);
            ...some more code... 
            myappend.call(tooaddto,  otherval);
      });
      

      【讨论】:

      • 谢谢,我将使用这个解决方案的一个版本。本质上,原型绑定了实现。是时候看看它是否会给我带来性能提升。
      猜你喜欢
      • 1970-01-01
      • 2022-11-11
      • 2019-06-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多