4034

在Java中,您可以使用对于循环遍历数组中的对象,如下所示:

String[]myStringArray={“Hello”,“World”};for(字符串s:myStringArray){//做点什么}

我可以用JavaScript做同样的事情吗?

10
  • 7
    好的,所以我有点困惑,在访问对象时可以使用增强的for循环吗?用一个顺序的来填充一个?这是正确的吗? 评论 2010年6月10日0:15
  • 54
    不,这很简单,数组对象有数字索引,所以您想迭代在这些按数字顺序排列的索引上,顺序循环确保增强 用于枚举对象属性,没有特定顺序,它还枚举继承的属性。。。对于迭代始终建议使用阵列上的顺序循环。。。 评论 2010年6月10日0:38
  • 7
    相关的-stackoverflow.com/questions/5349425/… 评论 2011年11月1日17:53
  • 9
    jsben.ch/#/Q9oD5<=这里是一系列阵列循环解决方案的基准 评论 2016年11月3日19:45
  • 14
    @CMS不,这并不简单。其他语言都很简单。这在JS中非常复杂在里面属于既可以使用,也可以做不同的事情。那么你也有对于每个以及丑陋而烦人的基于索引的循环。其他每一种现代语言都使得在一个集合上循环变得简单明了,没有任何意外或混乱。JS也可以,但它不能。 评论 2018年10月5日15:59

46个答案46

重置为默认值
5206

三个主要选项:

  1. for(vari=0;i<xs.length;i++){console.log(xs[i]);}
  2. xs.forEach((x,i)=>控制台.log(x));
  3. for(xs的常量x){console.log(x);}

下面是详细的示例。


1.顺序对于循环:

var myStringArray=[“Hello”,“World”];var arrayLength=myStringArray.length;for(var i=0;i<arrayLength;i++){console.log(myStringArray[i]);//做点什么}

赞成的意见

  • 适用于各种环境
  • 你可以使用打破持续流量控制语句

欺骗

  • 太冗长了
  • 迫切需要
  • 容易拥有非一次性错误(有时也称为围栏柱错误)

2数组原型.forEach:

这个欧洲标准5规范介绍了许多有益的数组方法。其中之一数组原型.forEach,为我们提供了一种在数组上迭代的简洁方法:

常量数组=[“一”,“二”,“三”]array.forEach(函数(项、索引){console.log(项,索引);});

ES5规范发布将近十年了(2009年12月),几乎所有现代引擎都在桌面、服务器和移动环境中实现了ES5规范,因此可以安全地使用它们。

使用ES6箭头函数语法,它更加简洁:

array.forEach(item=>console.log(item));

除非您计划支持古老的平台(例如。,Internet Explorer 11); 你去也很安全。

赞成的意见

  • 非常简短。
  • 声明的

欺骗

  • 无法使用打破/持续

通常情况下,您可以更换打破在迭代数组元素之前过滤数组元素,从而摆脱命令式循环,例如:

array.filter(item=>item.condition<10).forEach(项=>控制台.log(项))

如果要迭代数组,请记住从中构建另一个数组,您应该使用地图。我已经看过很多次这种反模式。

反彩色:

常数=[1,2,3,4,5],加倍=[];numbers.forEach((n,i)=>{加倍[i]=n*2});

的正确使用案例地图:

常数=[1,2,3,4,5];const doubled=numbers.map(n=>n*2);console.log(双倍);

此外,如果你想减少将数组转换为一个值,例如,如果要对一个数字数组求和,则应使用减少方法。

反彩色:

常数=[1,2,3,4,5];常数和=0;numbers.forEach(num=>{sum+=num});

正确使用减少:

常数=[1,2,3,4,5];常数和=数字减少((total,n)=>总数+n,0);console.log(总和);

3、ES6放弃声明:

这个欧洲标准6该标准引入了可迭代对象的概念,并定义了一种用于遍历数据的新构造,即用于。。。属于声明。

该语句适用于任何类型的可迭代对象,也适用于生成器(任何具有\[符号迭代器\]属性)。

根据定义,数组对象是ES6中内置的可迭代对象,因此可以对其使用以下语句:

让颜色=['red','green','blue'];for(颜色的恒定颜色){console.log(颜色);}

赞成的意见

  • 它可以对各种各样的对象进行迭代。
  • 可以使用正常的流量控制语句(打破/持续).
  • 用于迭代串行异步值。

欺骗

不要使用用于。。。在里面

@zipcodeman建议使用用于。。。在里面语句,但用于迭代数组放弃应该避免,这句话的意思是列举对象属性。

它不应用于类似阵列的对象,因为:

  • 迭代顺序不保证;数组索引不能按数字顺序访问。
  • 继承的属性也会被枚举。

第二点是,它会给您带来很多问题,例如,如果您扩展阵列原型对象中包含一个方法,该属性也将被枚举。

例如:

Array.prototype.foo=“foo!”;var数组=['a','b','c'];for(数组中的var i){console.log(数组[i]);}

上述代码将控制台记录“a”、“b”、“c”和“foo!”。

如果您使用一些严重依赖本地原型增强的库(例如框架).

这个放弃正如我之前所说,声明的目的是列举对象属性,例如:

变量obj={“a”:1,“b”:2,“c”:3};for(obj中的var属性){if(obj.hasOwnProperty(prop)){//或if(Object.prototype.hasOwnProperty.call(obj,prop))以确保安全。。。console.log(“prop:”+prop+“value:”+obj[prop])}}

在上面的示例中拥有自己的财产方法只允许枚举自有财产就是这样,只有对象物理上具有的属性,没有继承的属性。

我建议您阅读以下文章:

13
  • 13
    我知道这个答案早于async和Promises,但我觉得在任何有关现代JavaScript的对话中都值得一提:“对于每个不等待承诺。在使用承诺(或异步函数)作为对于每个回调。" (developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…) 评论 2021年6月15日11:41
  • 8
    es6的con放弃:无法获取当前索引
    – 维克
    评论 2021年9月9日1:13
  • 1
    @维克你可以,但这并不简单。 评论 2022年2月16日18:23
  • 4
    作为参考,这是如何在循环时获取当前索引。我个人觉得这很直截了当。for(yourArray.entries()的const[i,x]){…}. 评论 2022年5月14日16:28
  • 2
    对于那些看到这个答案并想知道是否应该选择For-of的每一个()的人,我建议使用For-of。for-of是一种更新的循环语法,它完全取代了forEach的需要。for-of提供的东西没有forEach提供的,但反过来却不是真的。 评论 2022年5月14日16:32
1206
+50

是的,假设您的实现包括对于...属于中引入的功能2015年ECMAScript(“和谐”版本)。。。现在这是一个相当安全的假设。

其工作原理如下:

//要求ECMASCRIPT 2015+var s,myStringArray=[“Hello”,“World”];用于myStringArray的{// ... 用s做某事。。。}

或者更好,因为ECMAScript 2015也提供了块范围变量:

//需要ECMASCRIPT 2015+const myStringArray=[“Hello”,“World”];for(myStringArray的常量){// ... 用s做某事。。。}//此处不再定义s

(变量在每个迭代中是不同的,但仍然可以声明常数在循环体中,只要不在那里进行修改。)

关于稀疏数组的一点注意:JavaScript中的数组实际上存储的项目可能没有它报告的那么多长度; 这个数字只是比存储值的最高索引大一。如果数组包含的元素少于其长度所指示的元素,则称为稀疏的例如,一个数组中只有索引3、12和247处的项是完全合理的;这个长度这样的数组有248个,尽管它实际上只存储3个值。如果您尝试访问任何其他索引处的项,则数组将显示未定义值,但数组与实际具有未定义存储的值。您可以通过多种方式看到这种差异,例如节点REPL显示阵列的方式:

>只有一个项的//数组,位于索引12[<12个空项目>,1]>[0]//在索引0处似乎未定义未定义>a[0]=undefined//但如果我们在那里放置一个实际的undefined未定义>现在看起来像这样[未定义,<11个空项>,1]

因此,当您想“循环”一个数组时,您需要回答一个问题:您想在由其长度和进程指示的整个范围内循环吗未定义是否只处理实际存在的元素?这两种方法都有大量的应用;这取决于您使用数组的目的。

如果使用对于..属于,则执行循环体长度时间,循环控制变量设置为未定义对于数组中实际不存在的任何项。根据“使用”代码的细节,该行为可能是您想要的,但如果不是,则应使用不同的方法。

当然,一些开发人员别无选择,只能使用不同的方法,因为无论出于何种原因,他们的目标是一个尚不支持的JavaScript版本对于...属于.

只要您的JavaScript实现符合以前的ECMAScript规范的版本(例如,它排除了9之前的Internet Explorer版本),然后您可以使用每个阵列的阵列号迭代器方法而不是循环。在这种情况下,您将传递一个函数,以便对数组中的每个项进行调用:

var myStringArray=[“Hello”,“World”];myStringArray.forEach(函数){// ... 用s做某事。。。} );

如果您的实现支持ES6+,那么当然可以使用箭头函数:

myStringArray.forEach(s=>{// ... 用s做某事。。。} );

不同于对于...属于,.对于每个只为数组中实际存在的元素调用函数。如果传递带有三个元素且长度为248的假设数组,它将只调用该函数三次,而不是248次。如果您想这样处理稀疏数组,.对于每个即使你的口译员支持对于...属于.

最后一个选项,适用于全部的JavaScript的版本,是显式计数循环。只需从0数到长度的1,然后将计数器用作索引。基本循环如下所示:

var i,s,myStringArray=[“Hello”,“World”],len=myStringArray.length;对于(i=0;i<len;++i){s=myStringArray[i];// ... 用s做某事。。。}

这种方法的一个优点是可以选择如何处理稀疏数组。上述代码将完整地运行循环体长度时间,使用设置为未定义对于任何缺少的元素,就像对于..属于; 如果您只想处理稀疏数组的实际当前元素,如.对于每个,您可以添加一个简单的在里面指数测试:

var i,s,myStringArray=[“Hello”,“World”],len=myStringArray.length;对于(i=0;i<len;++i){if(myStringArray中的i){s=myStringArray[i];// ... 用s做某事。。。}}

根据实现的优化,将长度值分配给局部变量(而不是包括完整的myStringArray.length(我的字符串数组长度)表达式在循环条件中)可以显著提高性能,因为它每次都跳过属性查找。您可能会在循环初始化子句中看到长度缓存,如下所示:

var i,len,myStringArray=[“Hello”,“World”];对于(len=myStringArray.length,i=0;i<len;++i){

显式计数循环还意味着您可以根据需要访问每个值的索引对于每个,因此您也可以这样访问它:

myStringArray.forEach(s,i)=>{// ... 用s和i做点什么。。。});

对于...属于不会为您提供与每个对象关联的索引,但只要您迭代的对象实际上是阵列(而不是其他可迭代类型之一对于..属于工作),您可以使用数组#项方法将其更改为[index,item]对数组,然后对其进行迭代:

for(myStringArray.entries()的const[i,s]){// ... 用s和i做点什么。。。}

这个对于...在里面其他人提到的语法用于循环对象的属性;因为JavaScript中的数组只是一个具有数字属性名的对象(并且会自动更新长度属性),理论上可以用它在数组上循环。但问题是,它并不局限于数值属性值(记住,即使是方法实际上也只是其值为闭包的属性),也不能保证按数字顺序迭代这些属性。因此对于...在里面语法应该用于在数组中循环。

1
  • 24
    请注意,一些解释器(例如V8)将自动缓存数组的长度如果代码被调用了足够的次数,它检测到循环没有修改长度。虽然缓存长度仍然很好,但当您的代码被调用足够的次数来真正产生影响时,它可能不会提供速度提升。
    – 弗罗兹
    评论 2012年6月4日16:29
453

你可以使用地图,这是一种函数式编程技术,在其他语言中也可用,如蟒蛇哈斯克尔.

[1,2,3,4].map(功能(项){警报(项目);})

一般语法为:

array.map(函数)

一般来说函数将接受一个参数,它是数组的一项。但在JavaScript的情况下,它可以接受第二个参数,即项的索引,第三个参数,也就是数组本身。

的返回值阵列.map是另一个数组,因此可以这样使用:

var x=[1,2,3,4].map(函数(项){返回项*10;});

现在x是[10,20,30,40].

您不必内联编写函数。它可以是一个单独的函数。

var item_processor=函数(项){//对一个项目做一些复杂的事情}new_list=my_list.map(项目处理器);

这相当于:

for(mylist中的项){itemprocessor(项);}

除非你没有得到新建列表(_L).

  • 105
    这个特定的示例可能更好地使用每个数组.地图用于生成新数组。
    – 哈托
    评论 2010年6月10日0:20
  • 21
    @哈森数组原型.map方法是ECMAScript第五版标准的一部分,尚未在所有实现中提供(例如IE缺少它),也适用于迭代在一个数组上我认为数组原型.forEach方法更多语义上对的。。。另外,请不要建议for-in语句,更多详细信息请参阅我的回答:) 评论 2010年6月10日0:30
  • @克里斯蒂安。Salvadó这个问题现在包含了ES5不可靠的回答和使用ES6箭头符号的回答。你还在站台上吗?我们什么时候变得这么老的?🥲 评论 3月8日9:55
143

for(myStringArray的常量){

(直接回答您的问题:现在您可以了!)

大多数其他答案都是正确的,但(在撰写本文时)他们没有提到ECMA脚本 6 2015带来了一种新的迭代机制用于。。属于循环。

这种新语法是在JavaScript中迭代数组的最优雅方式(只要您不需要迭代索引)。

它目前可以与Firefox 13+、Chrome 37+一起使用,但不能与其他浏览器一起使用(请参阅下面的浏览器兼容性)。幸运的是,我们有JavaScript编译器(例如巴别塔)这使我们今天能够使用下一代功能。

它也适用于Node.js(我在0.12.0版本上测试过它)。

迭代数组

//对于块范围,也可以使用“let”或“const”代替“var”。for(var字母[“a”,“b”,“c”]){console.log(字母);}

迭代对象数组

常数带=[{firstName:“John”,lastName:“Lennon”},{firstName:“Paul”,lastName:“McCartney”}];for(带的常量成员){console.log(member.firstName+“”+member.lastName);}

迭代生成器:

(示例摘自https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for…第页,共页)

function*fibonacci(){//生成器函数设[prev,curr]=[1,1];while(真){[上一个,当前]=[当前,上一个+当前];收益率;}}for(fibonacci()的常数n){console.log(n);//将序列截短为1000如果(n>=1000){断裂;}}

兼容性表: http://kangax.github.io/compat-table/es6/测试-用于。。循环(_L)

规范: http://wiki.ecmascript.org/doku.php?id=harmony:迭代器

}

0
132

在JavaScript中,不建议使用for-In循环遍历数组,但最好使用对于循环,例如:

对于(var i=0,len=myArray.length;i<len;i++){}

它也进行了优化(“缓存”数组长度)。如果你想了解更多,阅读我关于这个主题的帖子.

0
103

6种不同的方法在数组中循环

您可以通过许多不同的方法在数组中循环。我把我最喜欢的6种方法从上到下进行了排序。

1.使用JavaScript for循环

当它只是在数组中循环时对于循环是我的第一选择。

设数组=[1,2,3,4,5];for(设i=0;i<array.length;i++){console.log(数组[i]);}

2.使用forEach循环

对于每个loop是一种通过数组循环的现代方法。此外,它还提供了对数组和元素的更多灵活性和控制。

设数组=[1,2,3,4,5];array.forEach((元素)=>{console.log(元素);});

3.用于。。。属于

用于。。。属于循环使您可以直接访问数组元素。

设数组=[1,2,3,4,5];for(数组的let元素){console.log(元素);}

4.用于。。。在回路中

用于。。。在里面提供了一个键,您可以使用它访问数组元素。

设数组=[1,2,3,4,5];for(让索引进入数组){console.log(array[index]);}

5.使用while循环

while循环也可用于循环数组。

设数组=[1,2,3,4,5];让长度=array.length;while(长度>0){console.log(数组[array.length-length]);长度--;}

6.使用do…while循环

同样,我使用做……同时

设数组=[1,2,3,4,5];让长度=array.length;做{console.log(数组[array.length-length]);长度--;}while(长度>0)

94

Opera、Safari、Firefox和Chrome现在都共享了一组增强的Array方法,用于优化许多常见循环。

您可能不需要所有这些功能,但它们可能非常有用,或者如果每个浏览器都支持的话,它们也会非常有用。

Mozilla实验室发布了他们和网络工具包两者都使用,以便您可以自己添加它们。

滤波器返回满足某些条件或测试的项数组。

每一个如果每个数组成员都通过测试,则返回true。

一些如果有通过测试的,则返回true。

对于每个在每个数组成员上运行函数,但不返回任何内容。

地图类似于forEach,但它为每个元素返回一个运算结果数组。

这些方法都以一个函数作为第一个参数,并有一个可选的第二个参数,这是一个对象,当数组成员循环通过该函数时,您希望将其范围强加给数组成员。

忽略它,直到你需要它。

索引属于最后索引找到与参数完全匹配的第一个或最后一个元素的适当位置。

(函数(){var p,ap=阵列原型,p2={过滤器:函数(fun,scope){var L=此长度,A=[],i=0,val;if(typeof fun==“函数”){而(i<L){如果(我在此){val=此[i];if(fun.call(scope,val,i,this)){A[A.长度]=val;}}++i;}}返回A;},每个:功能(乐趣、范围){var L=长度,i=0;if(typeof fun==“函数”){而(i<L){if(i在this&&!fun.call(scope,this[i],i,this)中)返回false;++i;}返回true;}返回null;},forEach:功能(乐趣、范围){var L=此长度,i=0;if(typeof fun==“函数”){而(i<L){如果(我在此){有趣的调用(scope,this[i],i,this);}++i;}}返回此;},indexOf:函数(what,i){i=i||0;var L=此长度;而(i<L){if(this[i]===什么)返回i;++i;}返回-1;},lastIndexOf:函数(what,i){var L=此长度;i=i||L-1;如果(isNaN(i)||i>=L)i=L-1;其他的如果(i<0)i+=L;而(i>-1){if(this[i]===什么)返回i;--i;}返回-1;},地图:功能(趣味、范围){var L=this.length,A=数组(this.lendth),i=0,val;if(typeof fun==“函数”){而(i<L){如果(我在此){A[i]=fun.call(范围,this[i],i,this);}++i;}返回A;}},some:功能(乐趣、范围){var i=0,L=此长度;if(typeof fun==“函数”){而(i<L){if(i在this&&fun.call(scope,this[i],i,this)中)返回true;++i;}返回false;}}}for(p2中的p){if(!ap[p])ap[p]=p2[p];}返回true;})();
0
84

介绍

自从我上大学以来,我用Java、JavaScript、Pascal、,ABAP公司、PHP、,进度4GL,C/C++,可能还有其他一些我现在想不起来的语言。

虽然它们都有自己的语言特质,但每种语言都有许多相同的基本概念。这些概念包括程序/功能,国际单项体育联合会-声明,适用于-循环,以及WHILE(当)-循环。


传统的对于-回路

传统的对于循环有三个组件:

  1. 初始化:在第一次执行look块之前执行
  2. 条件:每次执行循环块之前检查一个条件,如果为false,则退出循环
  3. 事后思考:每次执行循环块后执行

这三个组件通过一个;符号。这三个组件的内容都是可选的,这意味着以下内容是最基本的对于可能的循环:

用于(;;){//做一些事情}

当然,您需要包括一个if(条件===true){break;}或者if(条件===true){return;}在里面的某个地方对于-循环以使其停止运行。

不过,通常情况下,初始化用于声明索引,条件用于将该索引与最小或最大值进行比较,而事后思考用于增加索引:

对于(var i=0,长度=10;i<长度;i++){控制台.log(i);}

使用传统对于循环遍历数组

在数组中循环的传统方法是:

for(var i=0,length=myArray.length;i<length;i++){console.log(myArray[i]);}

或者,如果您喜欢向后循环,可以这样做:

对于(var i=myArray.length-1;i>-1;i--){console.log(myArray[i]);}

然而,也有许多可能的变体,例如:

for(var key=0,value=myArray[key],length=myArray.length;key<length;value=myArray[++key]){console.log(值);}

…或者这个。。。

var i=0,长度=myArray.length;对于(;i<长度;){console.log(myArray[i]);i++;}

……或者这个:

var键=0,值;for(;value=myArray[key++];){console.log(值);}

无论哪种方法最有效,在很大程度上都取决于个人品味和您正在实现的特定用例。

请注意,所有浏览器都支持这些变体,包括非常古老的浏览器!


A类虽然

一种替代方案对于循环是一个虽然循环。要循环遍历数组,可以执行以下操作:

var键=0;while(value=myArray[key++]){console.log(值);}

像传统的对于循环,虽然即使是最古老的浏览器也支持循环。

此外,请注意,every-while循环可以重写为对于循环。例如虽然上述循环的行为与此完全相同对于-循环:

for(var key=0;value=myArray[key++];){console.log(值);}

对于。。。在里面用于。。。属于

在JavaScript中,您也可以这样做:

for(myArray中的i){console.log(myArray[i]);}

然而,这应该小心使用,因为它的行为与传统的不同对于在所有情况下都会出现循环,并且需要考虑潜在的副作用。请参见为什么在数组迭代中使用“for…in”是一个坏主意?了解更多详细信息。

作为替代方案对于。。。在里面,现在还有用于。。。属于。以下示例显示了用于。。。属于循环和a用于。。。在里面循环:

var myArray=[3,5,7];myArray.foo=“你好”;for(myArray中的var i){控制台.log(i);//日志0、1、2、“foo”}for(myArray的var i){控制台.log(i);//日志3、5、7}

此外,您需要考虑Internet Explorer的任何版本都不支持用于。。。属于(边缘12+dos)并且用于。。。在里面至少需要Internet Explorer 10。


Array.prototype.forEach()

替代对于-循环是Array.prototype.forEach(),使用以下语法:

myArray.forEach(函数(value、key、myArray){console.log(值);});

数组.原型.forEach()所有现代浏览器以及Internet Explorer 9和更高版本都支持。


图书馆

最后,许多实用程序库也有自己的foreach公司变化。AFAIK,三个最受欢迎的是:

jQuery.each(),英寸jQuery(jQuery):

$.each(myArray,函数(键,值){console.log(值);});

_.each(),英寸下划线.js:

_.each(myArray,function(value,key,myArray){console.log(值);});

_.forEach(),英寸洛达什:

_.forEach(myArray,函数(值,键){console.log(值);});
69

使用虽然循环。。。

var i=0,item,items=['one','two','three'];while(项目=项目[i++]){console.log(项);}

它记录:“一”、“二”和“三”

对于相反的顺序,一个更有效的循环:

var items=['one','two','three'],i=items.length;而(i-){console.log(项目[i]);}

它记录:“三个”、“两个”和“一个”

或者经典对于循环:

var项=['one','two','three']对于(var i=0,l=items.length;i<l;i++){console.log(项目[i]);}

它记录:“一”、“二”、“三”

参考:谷歌关闭:如何不写JavaScript

2
  • 22
    如果任何数组元素都是falsy,那么“while”语法的第一个示例将不起作用。 评论 2012年4月16日14:42
  • 2
    …而这个while循环等价于:for(var i=0,item;item=items[i];i++),这样就不需要事先声明索引和项变量。。。 评论 2013年3月31日19:09
41

如果你想要一种简洁的方法来编写一个快速循环您可以反向迭代:

for(var i=myArray.length;i---;){var项=myArray[i];}

这具有缓存长度的优点(类似于for(var i=0,len=myArray.length;i<len;++i)和不一样对于(var i=0;i<myArray.length;++i))而要键入的字符更少。

有时甚至应该反向迭代,例如在迭代活动节点列表您计划在迭代期间从DOM中删除项。

2
  • 17
    对于那些没有得到如此巧妙的东西的人:首先计算i-表达式,并允许循环在不出错时继续。。。然后计数器递减。一旦我变为零,它就会跳出循环,因为在Javascript中,零是一个错误的值。 评论 2013年3月1日12:09
  • 5
    法尔西什?你的意思是假的。让我们都坚持正确的术语,以避免混淆;) 评论 2013年4月27日7:33
39

中循环遍历数组的一些用例函数式编程方法在JavaScript中:

1.只需循环遍历一个数组

constmyArray=[{x:100},{x:200},}x:300}];myArray.forEach((元素、索引、数组)=>{console.log(element.x);//100, 200, 300console.log(索引);//0, 1, 2console.log(数组);//同一myArray对象3次});

注意:严格地说,Array.prototype.forEach()不是函数方法,因为它作为输入参数的函数不应该返回值,因此不能将其视为纯函数。

2.检查数组中的任何元素是否通过测试

const人员=[{姓名:'约翰',年龄:23},{姓名:'安德鲁',年龄:3},{姓名:'彼得',年龄:8},{姓名:“Hanna”,年龄:14},{姓名:'亚当',年龄:37}];const anyAdult=people.some(person=>person.age>=18);console.log(anyAdult);//真的

3.转换为新阵列

constmyArray=[{x:100},{x:200},}x:300}];const newArray=myArray.map(element=>element.x);console.log(newArray);//[100, 200, 300]

注意:map()方法创建一个新数组,其结果是对调用数组中的每个元素调用提供的函数。

4.总结一个特定属性,并计算其平均值

constmyArray=[{x:100},{x:200},}x:300}];constsum=myArray.map(element=>element.x).reduce((a,b)=>a+b,0);console.log(总和);//600 = 0 + 100 + 200 + 300const平均值=总和/myArray.length;console.log(平均值);//200

5.在原始数组的基础上创建一个新数组,但不进行修改

constmyArray=[{x:100},{x:200},}x:300}];const newArray=myArray.map(元素=>{返回{…元素,x: 元素.x*2};});console.log(myArray);//[100, 200, 300]console.log(newArray);//[200, 400, 600]

6.统计每个类别的数量

const人员=[{name:'John',group:'A'},{name:'Andrew',group:'C'},{name:“Peter”,group:“A”},{name:“James”,组:“B”},{name:“Hanna”,组:“A”},{名称:“Adam”,组:“B”}];const groupInfo=people.reduce((groups,person)=>{常数{A=0,B=0,C=0}=群;if(person.group===“A”){return{…groups,A:A+1};}else if(person.group===“B”){return{…groups,B:B+1};}其他{return{…groups,C:C+1};}}, {});console.log(groupInfo);//{A:3、C:1、B:2}

7.根据特定条件检索数组的子集

constmyArray=[{x:100},{x:200},}x:300}];const newArray=myArray.filter(element=>element.x>250);console.log(newArray);//[{x:300}]

注意:filter()方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。

8.对数组排序

const人员=[{name:“John”,年龄:21},{name:“Peter”,年龄:31},{name:“Andrew”,年龄:29},{姓名:“Thomas”,年龄:25岁}];let sortByAge=people.sort(函数(p1,p2){返回p1.age-p2.age;});console.log(sortByAge);

在此处输入图像描述

9.在数组中查找元素

const people=[{姓名:“john”,年龄:23},{name:“john”,年龄:43},{name:“jim”,年龄:101},{姓名:“鲍勃”,年龄:67}];const john=people.find(person=>person.name=='john');console.log(john);

在此处输入图像描述

方法返回满足所提供测试函数的数组中第一个元素的值。

工具书类

0
37

是的,您可以使用循环在JavaScript中执行相同操作,但不受限制这样做。在JavaScript中有很多方法可以对数组进行循环。想象一下,下面有一个数组,你想在上面做一个循环:

var arr=[1,2,3,4,5];

以下是解决方案:

1) For循环

A类对于在JavaScript中,循环是一种常见的数组循环方式,但它并不被视为大型数组的最快解决方案:

对于(var i=0,l=arr.length;i<l;i++){控制台.log(arr[i]);}

2) While循环

while循环被认为是通过长数组进行循环的最快方式,但它通常在JavaScript代码中使用较少:

设i=0;而(arr.length>i){控制台.log(arr[i]);i++;}

3) 边做边做
A类边做边做正在做与虽然有一些语法差异,如下所示:

设i=0;做{控制台.log(arr[i]);i++;}而(arr.length>i);

这些是执行JavaScript循环的主要方法,但还有其他几种方法。

我们还使用中的的用于在JavaScript中循环对象的循环。

还可以看看地图(),过滤器(),减少()等函数。他们可能比使用虽然对于.

如果您想更多地了解JavaScript中数组上的异步函数,那么这是一篇好文章。

函数式编程在当今的发展世界。有充分的理由:功能性技术可以帮助您编写更容易实现的声明性代码一目了然、重构和测试。

函数式编程的基石之一是它的特殊用途列表和列表操作。而这些正是听起来像是:事物的数组,以及你对它们所做的事情。但功能性思维方式对待他们的方式与你有点不同可能会这样。

这篇文章将仔细研究我喜欢称之为“大三个列表操作:映射、过滤和减少。裹住你的头围绕这三个功能是实现编写干净的功能代码,并为强大的函数式和反应式编程技术。

这也意味着您将不再需要编写for循环。

阅读更多>>在这里:

0
30

有一种方法可以做到这一点,即在循环中只有很少的隐式范围,并且不需要额外的变量。

变量i=0,项目;//请注意,这对于稀疏数组或假值来说很弱for(;item=myStringArray[i++];){项目;//这是索引处的字符串。}

或者如果你真的想得到身份证并拥有一个真正经典的对于循环:

变量i=0,len=myStringArray.length;//缓存长度对于(;i<len;i++){myStringArray[i];//如果计划更改数组的长度,则不要使用此选项}

现代浏览器都支持迭代器方法对于每个,地图,减少,滤波器以及上的许多其他方法阵列原型.

6
  • 请注意,如果代码被调用了足够的次数,并且它检测到循环没有修改长度,一些解释器(例如V8)将自动缓存数组的长度。
    – 弗罗兹
    评论 2012年6月4日16:28
  • 感谢@Phrogz提供的信息,VM确实可以进行很多优化,但由于较旧的浏览器没有这种功能,因此最好还是为其进行优化,因为它太便宜了。 评论 2012年6月26日1:43
  • 1
    @加布里埃尔:为什么?请给出实际示例,说明不缓存长度实际上是性能瓶颈。我遵循“过早优化是万恶之源”的方法。一旦我遇到问题,我会修复这个循环。。。 评论 2013年3月31日19:06
  • 1
    @StijndeWitt认为这只是一个风格问题。坦白地说,我甚至不再使用for循环,而是使用下划线来完成这些事情,比如_.each、_.map等。当我像这样写循环时,我主要缓存了长度,以便我的所有变量声明都位于函数顶部的一个位置。在这方面,遵循我的建议对任何实际应用都无关紧要。过早的优化是非常糟糕的,但如果优化碰巧是由风格决定引起的,我认为这实际上并不重要。 评论 2013年4月4日17:15
  • 1
    @Gabriel我相信JavaScript已经支持数组上的map函数,不需要为此引入额外的库。
    – 诺兹
    评论 2014年7月30日18:14
29

JavaScript中有多种循环数组的方法。

通用循环:

变量i;对于(i=0;i<子长度;++i){//使用`substr[i]执行操作`}

ES5用于每个:

substr.forEach(函数(项){//使用`item执行操作`});

jQuery.each(每个查询):

jQuery.each(子项、函数(索引、项){//用`item`做某事(如果你喜欢,`this`也是`item')});

看一看有关详细信息,也可以查看MDN公司用于在JavaScript中循环数组&使用jQuery检查每个的jQuery.

0
28

数组循环:

for(var i=0;i<things.length;i++){var事物=事物[i];console.log(thing);}

对象循环:

for(obj中的var属性){var propValue=对象[prop];console.log(propValue);}
28

我强烈建议使用下划线.js库。它为您提供了各种函数,您可以使用这些函数对数组/集合进行迭代。

例如:

_.each([1,2,3],函数(num){alert(num;});=>依次提醒每个号码。。。
2
  • 7
    对于这个问题的新发现者,我只想指出Lo-Dash系列Undercore的精神继承者,在许多方面都有所改进。 评论 2013年10月11日10:59
  • 为什么使用强调如果ECMA-262型已添加对于每个方法。本地代码总是更好。 评论 2015年6月23日23:32
27

如果有人对Array迭代可用的多种机制的性能方面感兴趣,我准备了以下JSPerf测试:

https://jsperf.com/fastest-array-iterator公司

性能结果

结果:

传统的for()迭代器是目前最快的方法,尤其是与缓存的数组长度.

设arr=[1,2,3,4,5];for(设i=0,大小=arr.length;i<大小;i++){//做点什么}

这个Array.prototype.forEach()Array.prototype.map()方法是最慢的近似,可能是由于函数调用开销.

4
  • 是更好的使用i=i+1而不是我++ 评论 2018年12月10日18:19
  • 2
    可以改进:请使用:++i而不是i++,这将避免临时对象。因此,它减少了内存使用量和cpu时间(无需分配)! 评论 2019年5月17日10:05
  • @PowerStat你能提供相关链接或参考吗?我从来没听说过,听起来很有趣。。。
    – 科尔西
    评论 2019年5月17日13:23
  • 1
    @colxi对于如此有趣的东西,你应该阅读Herb Sutter和Scott Meyers的核心C++内容。++i vs i++的东西来自《卓越C++:47工程难题、编程问题和解决方案-我的东西你也可以在上面找到哥特w.ca但对于每种编程语言都可以证明。 评论 2019年5月17日17:44
21

如果您正在使用jQuery库,请考虑使用http://api.jquery.com/jquery.each/

根据文档:

jQuery.each(集合、回调(indexInArray、valueOfElement))

退货: 对象

描述: 一个通用迭代器函数,可用于无缝迭代对象和数组。阵列和类似阵列具有长度属性的对象(例如函数的arguments对象)由数字索引迭代,从0到长度-1。其他对象包括通过其命名属性进行迭代。

这个$.each()函数与$(选择器).each(),这是用于以独占方式迭代jQuery对象。这个$.ech()美元函数可用于迭代任何集合,无论它是map(JavaScript对象)或数组。在数组的情况下回调被传递一个数组索引和相应的数组值时间。(也可以通过关键字,但Javascript将始终包装值作为对象即使是简单字符串或数值。)该方法返回其第一个参数,迭代的对象。

2
  • 6
    同意例外。不要低估额外依赖性的影响。除了已经大量使用jQuery的代码外,我建议不要这样做。 评论 2013年3月31日19:04
  • 2
    更新:这些天,您可以使用每个数组以获得与本机阵列大致相同的效果。 评论 2017年6月5日10:50
21

我还没有看到这种变化,我个人最喜欢这种变化:

给定数组:

var someArray=[“some”,“example”,“array”];

您可以在不访问长度属性的情况下对其进行循环:

for(var i=0,item;item=someArray[i];i++){//项是“some”,然后是“example”,最后是“array”//i是数组中项的索引警报(“someArray[”+i+“]:”+item);}

请参阅JsFiddle演示:http://jsfiddle.net/prvzk/

这仅适用于以下阵列稀疏。这意味着数组中的每个索引实际上都有一个值。然而,我发现实际上我很少在JavaScript中使用稀疏数组。。。在这种情况下,使用对象作为映射/哈希表通常容易得多。如果您确实有一个稀疏数组,并且希望在0上循环。。长度-1,需要for(var i=0;i<someArray.length;++i)构造,但仍然需要如果在循环中检查当前索引处的元素是否实际定义。

此外,正如CMS在下面的注释中提到的那样,您只能在不包含任何falsish值的数组上使用此选项。示例中的字符串数组可以工作,但如果您有空字符串,或者数字是0或NaN等,则循环将过早中断。同样,在实践中,这对我来说几乎从来都不是问题,但这是需要记住的,这使得在使用之前需要考虑这个循环……这可能会使某些人失去资格:)

我喜欢这个循环的地方是:

  • 写起来很短
  • 无需访问(更不用说缓存)长度属性
  • 要访问的项在循环中自动定义你选的名字下的尸体。
  • 与array.push和array.splice非常自然地结合使用列表/堆栈之类的数组

这样做的原因是数组规范要求当您从索引中读取一个项>=数组的长度时,它将返回未定义的值。当你写到这样的位置时,它实际上会更新长度。

对我来说,这个构造最接近我喜欢的Java 5语法:

for(字符串项:someArray){}

…还可以了解循环中的当前索引

2
  • 14
    请注意,使用这种方法,循环将在找到假值,例如空字符串,0,,NaN公司,无效的未定义,甚至在之前达到长度,例如:jsfiddle.net/prvzk/1 评论 2013年2月28日18:31
  • 循环条件可以是(item=someArray[i])!==未定义. 评论 2014年3月20日14:17
21

数组迭代有4种方式:

//1:用于for(设i=0;i<arr.length;++i){控制台.log(arr[i]);}//2:每个arr.forEach((v,i)=>控制台.log(v));//3:中的for(让我在arr中){控制台.log(arr[i]);}//4:第个,共个for(arr的常数v){console.log(v);}

总结:1和3解决方案创建额外的变量,2-创建额外的函数上下文。最好的方式是第四名-“for of”.

2
  • 2
    你愿意详细说明为什么4个“for of”比其他的更好吗 评论 2021年8月3日2:04
  • 1
    它不会创建不必要的变量或函数上下文。但如果你不在乎小缺点,你可以使用它们中的任何一个,什么对你来说更舒服@是的我谢谢你的问题。 评论 2021年8月3日9:39
21

神秘的

让a=[“Hello”,“World”];while(a.length){console.log(a.shift());}

性能测试

今天(2022-11-13),我在Chrome 107、Safari 15.2和Firefox 106上对选定的解决方案进行了测试。

结论

  • 对于所有阵列,解决方案C和D在所有浏览器上都是快速或最快的。
  • 对于所有阵列,解决方案A和B在所有浏览器上速度最慢

结果

在此处输入图像描述

细节

我执行了3项测试:

  • 小-用于2元素数组(如OP)-您可以运行它在这里
  • medium-用于10K元素数组,并且-您可以运行它在这里
  • 大-用于100K元素数组-您可以运行它在这里

下面的代码片段显示了测试中使用的代码。

函数A(A){设r=0;而(a.length)r+=a.shift().length;返回r;}功能B(a){设r=0;对于(i in a)r+=a[i].长度;返回r;}函数C(a){设r=0;对于(a的x)r+=x长度;返回r;}函数D(a){设r=0;对于(i=0;i<a.length;++i)r+=a[i].length;返回r;}函数E(a){设r=0;a.forEach(x=>r+=x长度);返回r;}let arr=[“Hello”,“World!”];[A,B,C,D,E].forEach(f=>控制台.log(`${f.name}:${f([…arr])}`)

以下是中等阵列的Chrome的示例结果:

在此处输入图像描述

10
  • 这是Haskell-y的方法;继续做第一个。聪明,但可能很慢。 评论 2020年1月16日2:49
  • @Sapphire_Brick实际上速度很快-这里是测试 评论 2020年7月24日10:06
  • 4
    你说得很好。我用1000个项目的数组运行了您的示例,并且while(a.length){console.log(a.shift());}速度大约是for(vari=0;i<a.length;i++){console.log(a[i]);}版本。¯\_(ツ)_/¯ 评论 2020年8月4日20:51
  • 即使你的母语中没有冠词,你也不应该漏掉英语中的冠词(不定冠词(“a”或“an”)和定冠词“the”)。参见示例。英语文章-修复常见语法错误的3条简单规则A、 AN,THE-英文文章. 评论 2020年10月30日8:35
  • 2
    @皮托利你说得对-我把答案回退到最初的形式。当我有更多的时间时,我会再次进行基准测试 评论 2021年3月1日5:21
18

有一种方法可以只迭代自己的对象属性,而不包括原型的属性:

for(数组中的var i)if(array.hasOwnProperty(i)){//使用数组[i]执行操作}

但它仍将迭代自定义属性。

在JavaScript中,任何自定义属性都可以分配给任何对象,包括数组。

如果要在稀疏数组上迭代,for(var i=0;i<array.length;i++)if(数组中的i)每个阵列具有es5垫片应该使用。

1
15

最优雅、最快捷的方式

var arr=[1,2,3,1023,1024];for(var值;值=arr.pop();){值+1}

http://jsperf.com/native-loop-performance/8


编辑(因为我错了)


比较遍历100000个项的数组的方法,并每次对新值进行最小操作。

准备工作:

<script src=“//code.jquery.com/jquery-2.1.0.min.js”></script><script src=“//cdnjs.cloudflare.com/ajax/libs/underline.js/1.6.0/nundercore-min.js”></script><脚本>Benchmark.prototype.setup=函数(){//对值执行最小操作的伪函数var tmp=0;var过程=函数(值){tmp=值;//保持对变量的引用(是否阻止发动机优化?)};//声明测试数组var arr=[];对于(var i=0;i<100000;i++)arr[i]=i;};</script>

测验:

<a href=“http://jsperf.com/native-loop-performance/16" title=“http://jsperf.com/native-loop-performance/16"><img src=“http://i.imgur.com/YTrO68E.png“title=”由imgur.com主持“/></a>
4
14

在JavaScript中有几种方法可以做到这一点。前两个示例是JavaScript示例。第三种方法使用JavaScript库,即jQuery使用.each()功能。

var myStringArray=[“hello”,“World”];for(myStringArray中的var i){警报(myStringArray[i]);}

var myStringArray=[“hello”,“World”];for(var i=0;i<myStringArray.length;i++){警报(myStringArray[i]);}

var myStringArray=[“hello”,“World”];$.each(myStringArray,函数(索引,值){警报(值);})
<script src=“https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js“></script>

1
  • 用于。。。在里面应避免使用类似阵列的对象
    – 布雷克
    评论 2016年12月5日5:25
14

优化的方法是缓存数组的长度并使用单变量模式,用单个变量初始化所有变量无功功率,无功功率关键字。

var i,max,myStringArray=[“Hello”,“World”];对于(i=0,max=myStringArray.length;i<max;i++){警报(myStringArray[i]);//做点什么}

如果迭代顺序无关紧要,那么您应该尝试反向循环。它是最快的,因为它减少了开销条件测试,并且在一个语句中减少了开销:

var i,myStringArray=[“item1”,“item2”];对于(i=myStringArray.length;i--){警报(myStringArray[i]);}

或者更好更干净地使用虽然循环:

var myStringArray=[“item1”,“item2”],i=myStringArray.length;同时(i--){//用水果做点什么}
13

在JavaScript中,有很多解决方案可以循环数组。

下面的代码是流行的代码

/**声明输入*/const items=[你好,世界]/**解决方案1。简单适用于*/console.log('解决方案1。简单用于')for(设i=0;i<items.length;i++){console.log(项目[i])}控制台.log()控制台.log()/**解决方案2。简单的while*/console.log('解决方案2。简单时间')设i=0while(i<items.length){console.log(项目[i++])}控制台.log()控制台.log()/**解决方案3。对于每个*/console.log('解决方案3。“每个”)项。forEach(项=>{console.log(项)})控制台.log()控制台.log()/**解决方案4。放弃*/console.log('解决方案4。for-of’)for(常量项){console.log(项)}控制台.log()控制台.log()

13

我认为最好的方法是使用Array.forEach函数。如果你不能使用它,我建议你从MDN那里购买聚乙烯填充物。为了使其可用,这无疑是在JavaScript中迭代数组的最安全方法。

Array.prototype.forEach()

因此,正如其他人所建议的,这几乎总是你想要的:

var数=[1,11,22,33,44,55,66,77,88,99111];var总和=0;numbers.forEach(函数(n)){总和+=n;});

这样可以确保在处理数组的范围内所需的任何内容都保持在该范围内,并且只处理数组的值,而不处理对象属性和其他成员,这就是用于。。中有个。

使用常规C样式对于循环在大多数情况下都有效。重要的是要记住,循环中的所有内容都与程序的其余部分共享其作用域,{}不会创建新的作用域。

因此:

var总和=0;var数=[1,11,22,33,44,55,66,77,88,99111];对于(var i=0;i<数字.长度;++i){总和+=数字[i];}警报(i);

将输出“11”-这可能是您想要的,也可能不是您想要的。

一个有效的jsFiddle示例:https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/

12

如果您想使用jQuery,它的文档中有一个很好的示例:

每个$.([52,97],函数(索引,值){警报(索引+“:”+值);});
12

它不是100%相同,但很相似:

var myStringArray=['Hello','World'];//数组使用[]而不是{}for(myStringArray中的var i){console.log(i+'->'+myStringArray[i]);//i是索引/键,不是项目}

1
  • 1
    这似乎会遇到与数组对象的其他for in用法类似的问题,因为原型成员变量也会被for in捕获。
    – 克兹凯
    评论 2012年4月18日15:34
11

例如,我在Firefox控制台中使用了:

[].forEach.call(document.getElementsByTagName('pre'),函数(e){控制台.log(e);})

您可以使用querySelectorAll获得相同的结果

document.querySelectorAll('pre').forEach((e)=>{console.log(e.textContent);})
<pre>文本1<pre>文本2<pre>文本3

不是你想要的答案吗?浏览标记的其他问题问你自己的问题.