jQuery.each实现与本机Array.forEach不同

时间:2012-10-26 23:09:45

标签: javascript jquery api foreach each

为什么其他优秀jQuery.each函数的设计与(现在)原生Array.forEach的设计不同? F.ex:

var arr = ['abc','def'];
arr.forEach(function(entry, index) {
    console.log(entry); // abc / def
});

这绝对有道理。但是jQuery选择将index作为第一个参数:

$.each(arr, function(index, entry) {
   console.log(entry);
});

有谁知道这个设计决定背后的原因?我总是广泛地使用$.each,但它始终告诉我索引是第一个参数,因为它很少使用。我知道jQuery通过this实现了一个直接引用,但是如果你这样做的话会非常混乱:

​var arr = ['abc','def'];
$.each(arr, function() {
    console.log(this === 'abc'); // false both times, since this is a String constructor
});​​​​​​​​​​​​​​​​​​​​​​​​​​​​​

并不是让我感到困扰,我更喜欢将原生的polyfill用于最常见的新数组函数,但我一直对设计决策感到好奇。也许它是在浏览器实现原生forEach并且遗留支持阻止他们更改它之前的较旧时间制作的,或者......?

或许,它是以这种方式设计的,因为它也可以在本机对象上使用,而不是把键放在回调值之前“有意义”......?

旁注:我知道underscore.js(也许还有其他库)反过来(更类似于原生函数)。

3 个答案:

答案 0 :(得分:14)

嗯,我想我们不得不问Resig先生自己对此有所解释。事实上, ECMAscript 262版本5 在jQuery设计和开发的时候并不是非常普遍,所以这肯定会发挥作用。由于它是这样设计的,因此他们不想在以后更改它并破坏所有现有代码。

事实上,在循环数组时,您更有可能要访问优先级高于其的索引。所以,对我来说,没有合理的解释为什么你首先将 index 传递给回调。

请放心,如果今天发明了jQuery,它们将遵循本机实现行为。

另一方面,如果它太烦你,你可以简单地创建一个快捷方式并使用原生的Array.prototype.forEach来迭代你的jQuery包装集:

var forEach = Function.prototype.call.bind( Array.prototype.forEach );

forEach( $('div'), function( node ) {
    console.log( node );
});

..对于标准 Arrays ,只需使用他们的原生原型。

答案 1 :(得分:6)

这实际上是在最后一个jQuery conf中提到的;不幸的是我不记得细节,但是如果你从中看到足够多的视频,我想你可以找到它(我认为它是在主题演讲之后的Q& A中,但是不引用我在那)。无论如何有人(我认为不是Resig本人,而是另一位高级jQuery组织成员)基本上说“jQuery有一些我们都知道有问题的东西(”每个“都是他们给出的例子之一)但是有数百万的那里的网站现在依赖于那些有问题的行为,所以我们现在无法改变它。“

所以从本质上讲,答案是他们做出了一个糟糕的决定(Resig是一个令人难以置信的程序员,但即使他并不完美)现在每个人都使用jQuery必须忍受其余的时间,因为库保持相对较高新版本的向后兼容性(让我们面对它,这是一件好事:你不想每次升级jQuery时都要重写整个网站。)

还值得一提的是,Underscore库 each方法具有与内置each相同的签名。实际上,Underscore的版本实际上使用内置版本(如果存在)以获得更好的性能,如果浏览器不支持内置each,则仅依赖其版本。由于jQuery对象只是数组,因此您可以轻松地将它们与_.each一起使用,并且由于Underscore在jQuery中缺少许多其他功能,因此它是一个很好的库来补充jQuery。

答案 2 :(得分:1)

我同意让key秒更有意义,但你必须记住$.each可以与对象或数组一起使用,对于你可能需要的对象钥匙因为它们有意义。