使用Jquery导致domManip的Javascript函数指针不是函数错误

时间:2011-02-24 18:20:22

标签: javascript jquery function-pointers

JQuery版本

jQuery JavaScript Library v1.4.4

问题

解决方案可能显而易见,但我正在摸不着头脑。

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

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的情况下对其进行了测试,并且函数指针有效。

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

浏览器测试

  • Firefox 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>

谢谢, dennmat

3 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:3)

执行此操作时:

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

你确实得到了对“append”函数的引用,但是你丢失了与jQuery对象的关系。因此,当它稍后被调用时,它没有this参考它。

在新的浏览器(和JavaScript引擎)中有一个名为“bind”的Function实例可以在这里做你想做的事情:

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

(当然,我不会用冗余调用来编写它,但这只是一个例子。)这会给你一个函数的引用,这个函数会调用“append”,而this是一个引用该jQuery对象。

答案 2 :(得分:1)

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

然而,您要防止的真实情况不是查找函数,而是多次查询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);
});