ECMA-/Javascripts Array.prototype.forEach
Javascript (ECMAscript) 从 1.6 版(ECMAscript 第 3 版,2005 年)开始支持 Array.prototype.forEach 方法。因此,相当多的浏览器已经支持该方法,并且与 jQuery 的 $.each()
方法相比,它的速度快得令人难以置信。
(实际上,无论哪个 Javascript 库,它都击败了所有实现)
与 jQuery 相比,它的速度大约快 60-70%。亲自尝试一下 JSPerf 上的 forEach 与 jQuery。
到目前为止,我使用它的唯一缺点是,我无法找到一种方法来尽早打破迭代。与 for
一样,while
和 do-while
有一个 break
语句,jQuery 的 .each()< /code> 支持
return false
来打破循环。
我研究了ECMAScript Edition 5 规范(我发现的最新版本),但他们没有提到从该循环中提前中断。
那么,问题来了,Douglas Crockford 先生会将此称为设计错误
吗?
我是否错过了一些东西并且可以尽早打破这样的循环?
编辑
感谢您迄今为止的回答。我想由于没有人提出“本机”解决方案,因此确实没有实现该解决方案(也许是一个功能?)。不管怎样,我不太喜欢建议的方法,所以我闲逛了一下,终于找到了一个我喜欢的方法(至少更好)。看起来像:
var div = document.createElement('div'),
divStyle = div.style,
support = jQuery.support,
arr = ['MozTransform', 'WebkitTransform', 'OTransform'];
arr.slice(0).forEach(function(v,i,a){
if(divStyle[v] === ''){
support.transform = v;
a.length = 0;
}
});
这是“真正的”生产代码。我寻找一种很好的方法来查找 css3 转换属性,但我迷失在 ecma5 规范和规范中。奇怪的 Javascript 论坛:-)
因此,您可以将数组对象本身作为第三个参数传递到 .forEach
回调中。我从原始数组创建一个副本,调用 slice(0)
并在找到所需内容后立即将其 .length
属性设置为 0。效果很好。
如果有人提出更好的解决方案,我当然会编辑它。
Javascript (ECMAscript) supports the Array.prototype.forEach
method since version 1.6 (ECMAscript edition 3, 2005). So quite a lot of browser already support that method and it's incredibly fast in comparison to jQuery's $.each()
method for instance.
(Actually it beats all implementations, regardless which Javascript library)
In comparison to jQuery it's about 60-70% faster. Try it yourself on forEach vs. jQuery on JSPerf.
The only downside I have so far using it is, I can't figure a way to break the iteration early. Like for
, while
and do-while
have a break
statement, jQuerys .each()
supports the return false
to break the loop.
I looked into the ECMAScript Edition 5 Specifications (the latest I found), but they don't mention an early break from that loop.
So, question, would Mr. Douglas Crockford call this a design error
?
Am I missing something and it is possible to break such a loop early?
Edit
Thanks for the answers so far. I guess since nobody came up with a "native" solution, there really is no implementation for that (maybe a feature?). Anyway, I don't really like the suggested methods so I fooled around a little and finally found one I do like (at least, better). Looks like:
var div = document.createElement('div'),
divStyle = div.style,
support = jQuery.support,
arr = ['MozTransform', 'WebkitTransform', 'OTransform'];
arr.slice(0).forEach(function(v,i,a){
if(divStyle[v] === ''){
support.transform = v;
a.length = 0;
}
});
This is "real" production code. I looked for a nice way to lookup the css3 transform properties and I got lost in ecma5 specs & weird Javascript forums :-)
So, you may pass the array object itself as third parameter into the .forEach
callback. I create a copy from the original array, calling slice(0)
and set its .length
property to 0 as soon as I found what I'm looking for. Works quite well.
If someone comes up with a better solution I'll edit this of course.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
好吧,您可以使用
every
来代替。如果提供的回调函数为数组中的每个元素返回true
(真值),则该函数将返回true
,否则返回false
。这里的关键点是,一旦回调函数返回一个错误值,every
立即返回false
,而不迭代数组的其余部分。因此,只需忽略返回值,并将every
视为forEach
。在此示例中,
alert
只会触发 3 次。当然,这里需要注意的是,如果您希望循环继续,您必须返回一个真值。事实上,如果您不返回任何内容(未定义),则循环将停止。或者,您可以使用
some
,其行为方式完全相反;当回调函数返回 true 值时,立即返回 true;如果从未返回 true 值,则立即返回 false。在这种情况下,return true
将是您的“break”语句。向后是的,但它使您不必简单地返回 true 来让循环继续。现在,如果您关心性能,我建议仅使用普通的
for
循环,因为调用函数时会产生显着的开销,因为这会在较大的数组中快速累加。使用本机函数会有所帮助,但重复调用用户定义函数的开销仍然存在,而且并非微不足道。至少这是我的经验,你当然应该做自己的测试。Well, you could use
every
instead. The function is designed to returntrue
if the provided callback function returnstrue
(truthy) for every element in the array, andfalse
otherwise. Key point here is that once the callback function returns a falsly value,every
immediatly returnsfalse
without iterating over the rest of the array. So just ignore the return value, and treatevery
as if it wereforEach
.In this example,
alert
will only fire 3 times.Of course the big cavet here is that you must return a truthy value if you want the loop to continue. In fact if you return nothing (undefined) the loop will stop. Alternativly, you could use
some
which behaves in the exact opposite manner; immediatly returns true when the callback function returns a truthy value and false if it never does. In this case,return true
would be your "break" statement. Backwards yes, but it saves you from having toreturn true
simply to have the loop continue.Now, if you are concerened with performance, I'd recomend just using a normal
for
loop, as there is significant overhead incurred when calling functionas that will add up very quickly with larger arrays. Using native functions helps somewhat, but the overhead of repeated calls to user-defined functions still exists and is non-trivial. At least this has been my experience, you should of course do your own testing.您可以抛出一个错误来中断迭代:
这不太漂亮。我同意——规格错误。
You could throw an error to break out of the iteration:
This isn't exactly pretty. I agree -- spec bug.
我假设您有一大块代码需要针对每个元素运行。不要使用
forEach
来查找元素或类似的“停在中间”操作。将此函数应用于数组中的每个元素。你可以(我认为)使用某种全局指示器来检查并返回 false 如果“找到”或其他东西。
I would assume that you have a chunk of code that needs to be run against every single element. Don't use
forEach
to find an element or likewise "stop in the middle" operations. Apply this function to every element in an array.You could (I think) use some sort of global indicator to check and return false if "found" or something.
我想如果我想循环搜索,我会使用其他一些构造。
打破 forEach-ing 的一个选项当然是
抛出
某些东西,尽管这并不是人们真正想要使用 throw 的方式...I think I'd use some other construct if I want to loop to search.
An option to break out of the forEach-ing is of course to
throw
something, though it's not really the way one would want to use throw...