Javascript(ECMAscript)支持自1.6版本以来的Array.prototype.forEach
方法(ECMAscript edition 3,2005)。因此,相当多的浏览器已经支持该方法,并且与jQuery的$.each()
方法相比,它的速度非常快。
(实际上它胜过所有实现,无论哪个Javascript库)
与jQuery相比,它的速度提高了约60-70%。在JSPerf上的forEach vs. jQuery上自己尝试一下。
到目前为止我唯一使用它的缺点是,我无法想办法尽早打破迭代。与for
,while
和do-while
有break
语句一样,jQuerys .each()
支持return false
来打破循环。
我查看了 ECMAScript第5版规范(我发现的最新版本),但他们没有提到该循环的早期中断。
那么,问题一下,Douglas Crockford先生会称之为design error
吗?
我错过了什么,有可能提前打破这样的循环吗?
修改
感谢目前为止的答案。我想既然没有人想出一个“原生”解决方案,那真的没有实现(可能是一个功能?)。无论如何,我真的不喜欢建议的方法,所以我愚弄了一点,最后找到了一个我喜欢的(至少,更好)。看起来像:
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 specs&奇怪的Javascript论坛: - )
因此,您可以将数组对象本身作为第三个参数传递给.forEach
回调。我从原始数组创建一个副本,调用slice(0)
并在找到我正在寻找的内容时将其.length
属性设置为0。效果很好。
如果有人提出了更好的解决方案,我当然会对此进行编辑。
答案 0 :(得分:7)
好吧,您可以使用every
代替。如果提供的回调函数为数组中的每个元素返回true
(truthy),则该函数被设计为返回true
,否则返回false
。这里的关键点是,一旦回调函数返回一个错误值,every
立即返回false
而不迭代数组的其余部分。因此,只需忽略返回值,并将every
视为forEach
。
[1, 2, 3, 4, 5].every(function(e) {
alert(e);
if (e > 2) return false; //break
return true;
});
在此示例中,alert
只会触发3次。
当然,最重要的一点是,如果你想让循环继续,必须返回一个真值。事实上,如果你什么都不返回(未定义),循环将停止。或者,您可以使用some
,其行为完全相反;当回调函数返回一个truthy值时,immediatly返回true,如果它从未返回,则返回false。在这种情况下,return true
将是您的“休息”声明。向后是的,但它可以让你免于return true
只是让循环继续。
现在,如果你对性能有所了解,我建议只使用一个普通的for
循环,因为调用functionas时会产生很大的开销,而这些函数会在较大的数组中很快加起来。使用本机函数有所帮助,但重复调用用户定义函数的开销仍然存在且非常重要。至少这是我的经验,你当然应该做自己的测试。
答案 1 :(得分:1)
我认为你需要针对每个元素运行一大堆代码。不要使用forEach
来查找元素或同样“停在中间”操作。将此函数应用于数组中的每个元素。
你可以(我认为)使用某种全局指标来检查并返回false,如果“找到”或其他什么。
var found = false;
array.forEach(function (k, v) {
if (found)
{
return false;
}
else
{
if (v == 1)
{
found = true;
}
}
});
答案 2 :(得分:1)
你可以抛出一个错误来突破迭代:
if (typeof BreakIteration == "undefined") {
BreakIteration = new Error("BreakIteration");
}
try {
[0,1,2,3,4].forEach(function(key, value) {
console.log(key + ': ' + value);
if (value == 3) {
throw BreakIteration;
}
});
} catch (error) {
if (error !== BreakIteration) {
throw error;
}
}
这不是很漂亮。我同意 - spec bug。
答案 3 :(得分:0)
如果我想循环搜索,我想我会使用其他一些构造。
打破forEach-ing的选项当然是throw
的东西,虽然它不是真正想要使用throw的方式......