提问人:Mark Szymanski 提问时间:6/10/2010 最后编辑:Mateen UlhaqMark Szymanski 更新时间:11/13/2023 访问量:5330513
在 JavaScript 中遍历数组
Loop through an array in JavaScript
问:
在 Java 中,您可以使用循环遍历数组中的对象,如下所示:for
String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray) {
// Do something
}
我可以在 JavaScript 中做同样的事情吗?
答:
三个主要选项:
for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }
xs.forEach((x, i) => console.log(x));
for (const x of xs) { console.log(x); }
详细示例如下。
1.顺序循环:for
var myStringArray = ["Hello","World"];
var arrayLength = myStringArray.length;
for (var i = 0; i < arrayLength; i++) {
console.log(myStringArray[i]);
//Do something
}
优点
- 适用于各种环境
- 可以使用 和 流控制语句
break
continue
缺点
- 太啰嗦了
- 祈使的
- 容易出现偏离一的错误(有时也称为围栏柱错误))
2. :Array.prototype.forEach
ES5 规范引入了许多有益的数组方法。其中之一,Array.prototype.forEach
,为我们提供了一种简洁的方法来遍历数组:
const array = ["one", "two", "three"]
array.forEach(function (item, index) {
console.log(item, index);
});
ES5 规范发布(2009 年 12 月)已经快十年了,桌面、服务器和移动环境中几乎所有的现代引擎都实现了它,因此使用它们是安全的。
使用 ES6 箭头函数语法,它更加简洁:
array.forEach(item => console.log(item));
箭头功能也被广泛实现,除非您计划支持古老的平台(例如,Internet Explorer 11);你也可以安全离开。
优点
- 非常简短和简洁。
- 声明
缺点
- 无法使用
break
/continue
通常,您可以通过在迭代数组元素之前过滤数组元素来替换命令性循环的需要,例如:break
array.filter(item => item.condition < 10)
.forEach(item => console.log(item))
请记住,如果要迭代一个数组以从中构建另一个数组,则应使用 .我已经见过很多次这种反模式了。map
反模式:
const numbers = [1,2,3,4,5], doubled = [];
numbers.forEach((n, i) => { doubled[i] = n * 2 });
地图的正确用例:
const numbers = [1,2,3,4,5];
const doubled = numbers.map(n => n * 2);
console.log(doubled);
此外,如果您尝试将数组减少到一个值,例如,您想要对数字数组求和,则应使用 reduce 方法。
反模式:
const numbers = [1,2,3,4,5];
const sum = 0;
numbers.forEach(num => { sum += num });
减少的正确使用:
const numbers = [1,2,3,4,5];
const sum = numbers.reduce((total, n) => total + n, 0);
console.log(sum);
3. ES6 语句:for-of
ES6 标准引入了可迭代对象的概念,并定义了用于遍历数据的新构造,即语句。for...of
此语句适用于任何类型的可迭代对象,也适用于生成器(具有 \[Symbol.iterator\]
属性的任何对象)。
根据定义,数组对象是 ES6 中内置的可迭代对象,因此您可以对它们使用以下语句:
let colors = ['red', 'green', 'blue'];
for (const color of colors){
console.log(color);
}
优点
- 它可以遍历各种各样的对象。
- 可以使用正常的流控制语句 ( / )。
break
continue
- 可用于循环访问串行异步值。
缺点
- 如果您的目标是较旧的浏览器,则转译的输出可能会让您感到惊讶。
请勿使用for...in
@zipcodeman建议使用该语句,但对于迭代数组应避免,该语句旨在枚举对象属性。for...in
for-in
它不应用于类似数组的对象,因为:
- 不保证迭代顺序;数组索引不能按数字顺序访问。
- 还枚举了继承的属性。
第二点是,它可能会给你带来很多问题,例如,如果你扩展对象以包含一个方法,该属性也会被枚举。Array.prototype
例如:
Array.prototype.foo = "foo!";
var array = ['a', 'b', 'c'];
for (var i in array) {
console.log(array[i]);
}
上面的代码将控制台日志“a”、“b”、“c”和“foo!”。
如果您使用一些严重依赖原生原型增强的库(例如 MooTools),这可能是一个特别严重的问题。
正如我之前所说,该语句用于枚举对象属性,例如:for-in
var obj = {
"a": 1,
"b": 2,
"c": 3
};
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
// or if (Object.prototype.hasOwnProperty.call(obj,prop)) for safety...
console.log("prop: " + prop + " value: " + obj[prop])
}
}
在上面的示例中,该方法仅允许枚举自己的属性。就是这样,只有对象物理上具有的属性,没有继承的属性。hasOwnProperty
我建议您阅读以下文章:
评论
forEach
forEach
)
for-of
for (const [i, x] of yourArray.entries()) { ... }
您可以使用 ,这是一种函数式编程技术,在 Python 和 Haskell 等其他语言中也可用。map
[1,2,3,4].map( function(item) {
alert(item);
})
一般语法为:
array.map(func)
通常采用一个参数,该参数是数组的一个项目。但是在 JavaScript 的情况下,它可以采用第二个参数,即项目的索引,以及第三个参数,即数组本身。func
的返回值是另一个数组,因此您可以像这样使用它:array.map
var x = [1,2,3,4].map( function(item) {return item * 10;});
现在 x 是 .[10,20,30,40]
您不必以内联方式编写函数。它可以是一个单独的函数。
var item_processor = function(item) {
// Do something complicated to an item
}
new_list = my_list.map(item_processor);
这相当于:
for (item in my_list) {item_processor(item);}
除非你没有得到 .new_list
评论
Array.forEach
map
Array.prototype.forEach
方法在语义上更正确......另外,请不要建议 for-in 语句,请参阅我的回答以获取更多详细信息:)Array.prototype.map
Opera、Safari、Firefox 和 Chrome 现在都共享一组增强的 Array 方法,用于优化许多常见循环。
您可能不需要所有这些,但它们可能非常有用,或者如果每个浏览器都支持它们,它们就会非常有用。
Mozilla Labs 发布了他们和 WebKit 都使用的算法,因此您可以自己添加它们。
filter 返回满足某些条件或测试的项的数组。
如果每个数组成员都通过测试,则 every 返回 true。
如果有任何通过测试,则返回 true。
forEach 在每个数组成员上运行一个函数,并且不返回任何内容。
map 类似于 forEach,但它返回每个元素的操作结果数组。
这些方法都采用一个函数作为其第一个参数,并具有可选的第二个参数,该参数是一个对象,当数组成员遍历该函数时,您希望将其作用域强加给数组成员。
忽略它,直到你需要它。
indexOf 和 lastIndexOf 查找与其参数完全匹配的第一个或最后一个元素的适当位置。
(function(){
var p, ap= Array.prototype, p2={
filter: function(fun, scope){
var L= this.length, A= [], i= 0, val;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
val= this[i];
if(fun.call(scope, val, i, this)){
A[A.length]= val;
}
}
++i;
}
}
return A;
},
every: function(fun, scope){
var L= this.length, i= 0;
if(typeof fun== 'function'){
while(i<L){
if(i in this && !fun.call(scope, this[i], i, this))
return false;
++i;
}
return true;
}
return null;
},
forEach: function(fun, scope){
var L= this.length, i= 0;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
fun.call(scope, this[i], i, this);
}
++i;
}
}
return this;
},
indexOf: function(what, i){
i= i || 0;
var L= this.length;
while(i< L){
if(this[i]=== what)
return i;
++i;
}
return -1;
},
lastIndexOf: function(what, i){
var L= this.length;
i= i || L-1;
if(isNaN(i) || i>= L)
i= L-1;
else
if(i< 0) i += L;
while(i> -1){
if(this[i]=== what)
return i;
--i;
}
return -1;
},
map: function(fun, scope){
var L= this.length, A= Array(this.length), i= 0, val;
if(typeof fun== 'function'){
while(i< L){
if(i in this){
A[i]= fun.call(scope, this[i], i, this);
}
++i;
}
return A;
}
},
some: function(fun, scope){
var i= 0, L= this.length;
if(typeof fun== 'function'){
while(i<L){
if(i in this && fun.call(scope, this[i], i, this))
return true;
++i;
}
return false;
}
}
}
for(p in p2){
if(!ap[p])
ap[p]= p2[p];
}
return true;
})();
在 JavaScript 中,不建议使用 for-in 循环遍历 Array,但最好使用循环,例如:for
for(var i=0, len=myArray.length; i < len; i++){}
它也进行了优化(“缓存”数组长度)。如果您想了解更多信息,请阅读我关于该主题的帖子。
有一种方法可以做到这一点,你的循环中隐式作用域非常小,并消除了额外的变量。
var i = 0,
item;
// Note this is weak to sparse arrays or falsey values
for ( ; item = myStringArray[i++] ; ){
item; // This is the string at the index.
}
或者,如果你真的想得到 id 并有一个非常经典的循环:for
var i = 0,
len = myStringArray.length; // Cache the length
for ( ; i < len ; i++ ){
myStringArray[i]; // Don't use this if you plan on changing the length of the array
}
现代浏览器都支持迭代器方法、 、 和 Array 原型上的许多其他方法。forEach
map
reduce
filter
评论
使用 while 循环...
var i = 0, item, items = ['one', 'two', 'three'];
while(item = items[i++]){
console.log(item);
}
它记录:“一”、“二”和“三”
对于相反的顺序,一个更有效的循环:
var items = ['one', 'two', 'three'], i = items.length;
while(i--){
console.log(items[i]);
}
它记录:“三”、“二”和“一”
或者经典循环:for
var items = ['one', 'two', 'three']
for(var i=0, l = items.length; i < l; i++){
console.log(items[i]);
}
它记录:'one','two','three'
参考资料:Google Closure:如何不编写 JavaScript
评论
有一种方法可以只遍历自己的对象属性,不包括原型的属性:
for (var i in array) if (array.hasOwnProperty(i)) {
// Do something with array[i]
}
但它仍然会迭代自定义的属性。
在 JavaScript 中,任何自定义属性都可以分配给任何对象,包括数组。
如果要遍历稀疏数组,则应使用或 with。for (var i = 0; i < array.length; i++) if (i in array)
array.forEach
es5shim
评论
for (var i in array) if (++i)
是的,假设您的实现包括 for
...之
在 ECMAScript 2015(“Harmony”版本)中引入的功能...如今,这是一个非常安全的假设。
它的工作原理如下:
// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
// ... do something with s ...
}
或者更好的是,因为 ECMAScript 2015 还提供了块范围的变量:
// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
// ... do something with s ...
}
// s is no longer defined here
(该变量在每次迭代中都不同,但只要不在此处修改,仍然可以在循环体中声明。s
const
关于稀疏数组的说明:JavaScript 中的数组实际上可能存储的项与其报告的一样多;该数字仅比存储值的最高索引大 1。如果数组包含的元素少于其长度所指示的元素,则称其为稀疏。例如,在索引 3、12 和 247 处有一个包含项的数组是完全合法的;这样的数组是 248,尽管它实际上只存储了 3 个值。如果尝试访问任何其他索引处的项,则该数组似乎具有该值,但该数组仍与实际存储了值的数组不同。您可以通过多种方式看到这种差异,例如,在 Node REPL 显示数组的方式中:length
length
undefined
undefined
> a // array with only one item, at index 12
[ <12 empty items>, 1 ]
> a[0] // appears to have undefined at index 0
undefined
> a[0]=undefined // but if we put an actual undefined there
undefined
> a // it now looks like this
[ undefined, <11 empty items>, 1 ]
因此,当你想“遍历”一个数组时,你需要回答一个问题:你是想遍历由其长度指示的整个范围,并处理任何缺失的元素,还是只想处理实际存在的元素?这两种方法都有很多应用;这只取决于你使用数组做什么。undefined
如果使用 ..循环访问数组,则循环的主体将执行多次,并且循环控制变量将设置为数组中实际不存在的任何项。根据“执行某些操作”代码的详细信息,该行为可能是您想要的,但如果不是,则应使用其他方法。for
of
length
undefined
当然,一些开发人员别无选择,只能使用不同的方法,因为无论出于何种原因,他们的目标是尚不支持 ....for
of
只要您的 JavaScript 实现符合以前版本的 ECMAScript 规范(例如,该规范排除了 Internet Explorer 9 之前的版本),就可以使用 Array#forEach
迭代器方法而不是循环。在这种情况下,您需要在数组中的每个项目上传递一个要调用的函数:
var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) {
// ... do something with s ...
} );
当然,如果你的实现支持 ES6+,你可以使用箭头函数:
myStringArray.forEach( s => {
// ... do something with s ...
} );
与 ...不同,它只为数组中实际存在的元素调用函数。如果传递了具有三个元素且长度为 248 的假设数组,它只会调用函数 3 次,而不是 248 次。如果这是您想要处理稀疏数组的方式,那么即使您的解释器支持 ....for
of
.forEach
.forEach
for
of
最后一个选项适用于所有版本的 JavaScript,是显式计数循环。您只需从 0 数到比长度少 1 的数,然后使用计数器作为索引。基本循环如下所示:
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
s = myStringArray[i];
// ... do something with s ...
}
此方法的一个优点是可以选择如何处理稀疏数组。上面的代码将完整次运行循环的主体,设置为任何缺失的元素,就像 ..;如果您只想处理稀疏数组中实际存在的元素,例如 ,则可以在索引上添加一个简单的测试:length
s
undefined
for
of
.forEach
in
var i, s, myStringArray = [ "Hello", "World" ], len = myStringArray.length;
for (i=0; i<len; ++i) {
if (i in myStringArray) {
s = myStringArray[i];
// ... do something with s ...
}
}
根据实现的优化,将长度值分配给局部变量(而不是在循环条件中包含完整表达式)可能会对性能产生重大影响,因为它每次都会跳过属性查找。您可能会看到在循环初始化子句中完成的长度缓存,如下所示:myStringArray.length
var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {
显式计数循环还意味着您可以根据需要访问每个值的索引。索引也作为额外的参数传递给您传递给的函数,因此您也可以以这种方式访问它:forEach
myStringArray.forEach( (s,i) => {
// ... do something with s and i ...
});
for
...不会给你与每个对象关联的索引,但只要你正在迭代的对象实际上是 的实例(而不是其他可迭代类型之一),你就可以使用 Array#entries 方法将其更改为 [index, item] 对的数组,然后循环访问它:of
Array
for
of
for (const [i, s] of myStringArray.entries()) {
// ... do something with s and i ...
}
这。。。其他人提到的语法是用于遍历对象的属性;由于 JavaScript 中的 Array 只是一个具有数字属性名称(以及自动更新的属性)的对象,因此理论上您可以使用它循环访问数组。但问题在于,它并不局限于数值属性值(请记住,即使是方法实际上也只是值为闭包的属性),也不能保证按数字顺序迭代这些属性。因此,...语法不应用于遍历 Arrays。for
in
length
for
in
评论
我强烈建议使用 Underscore.js 库。它为您提供了各种函数,可用于遍历数组/集合。
例如:
_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...
评论
它不是 100% 相同,而是相似的:
var myStringArray = ['Hello', 'World']; // The array uses [] not {}
for (var i in myStringArray) {
console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
}
评论
如果你想要一种简洁的方法来编写一个快速循环,你可以反向迭代:
for (var i=myArray.length;i--;){
var item=myArray[i];
}
这样做的好处是缓存长度(类似于和不同),同时要键入的字符更少。for (var i=0, len=myArray.length; i<len; ++i)
for (var i=0; i<myArray.length; ++i)
甚至有些时候你应该反向迭代,比如在迭代期间迭代一个实时的 NodeList 时,你计划在迭代期间从 DOM 中删除项目。
评论
如果您使用的是 jQuery 库,请考虑使用 http://api.jquery.com/jQuery.each/
从文档中:
jQuery.each( collection, callback(indexInArray, valueOfElement) )
返回: 对象
描述:一个通用的迭代器函数,可用于 无缝迭代对象和数组。数组和类数组 具有 Length 属性的对象(例如函数的 arguments 对象) 按数字索引迭代,从 0 到 length-1。其他对象包括 通过其命名属性进行迭代。
该函数与 不同,后者是 用于以独占方式循环访问 jQuery 对象。该函数可用于遍历任何集合,无论是 map(JavaScript 对象)或数组。对于数组, callback 分别传递一个数组索引和一个对应的数组值 时间。(该值也可以通过关键字访问,但 Javascript 将始终将值包装为 一个简单的字符串或数字值。该方法返回其第一个 参数,被迭代的对象。
$.each()
$(selector).each()
$.each()
this
this
Object
评论
我还没有看到这种变化,我个人最喜欢它:
给定一个数组:
var someArray = ["some", "example", "array"];
您可以在不访问 length 属性的情况下遍历它:
for (var i=0, item; item=someArray[i]; i++) {
// item is "some", then "example", then "array"
// i is the index of item in the array
alert("someArray[" + i + "]: " + item);
}
请参阅此 JsFiddle 演示: http://jsfiddle.net/prvzk/
这仅适用于非稀疏数组。这意味着数组中的每个索引实际上都有一个值。但是,我发现在实践中,我几乎从未在 JavaScript 中使用过稀疏数组......在这种情况下,将对象用作映射/哈希表通常要容易得多。如果你确实有一个稀疏数组,并且想要遍历 0 ..length-1,你需要 for (var i=0; i<someArray.length; ++i) 构造,但你仍然需要一个内部循环来检查当前索引处的元素是否真的被定义了。if
此外,正如 CMS 在下面的评论中提到的,您只能在不包含任何虚假值的数组上使用它。示例中的字符串数组有效,但如果字符串为空,或者数字为 0 或 NaN 等,则循环将过早中断。同样,在实践中,这对我来说几乎从来都不是问题,但这是要记住的事情,这使得在使用它之前要考虑这个问题......这可能会使某些人失去资格:)
我喜欢这个循环的地方是:
- 写起来很短
- 无需访问(更不用说缓存)length 属性了
- 要访问的项目在循环中自动定义 正文。
- 非常自然地与 array.push 和 array.spice 结合使用列表/堆栈等数组
这样做的原因是数组规范要求,当您从索引 >= 数组的长度中读取项目时,它将返回 undefined。当您写入这样的位置时,它实际上会更新长度。
对我来说,这个结构最接近于我喜欢的 Java 5 语法:
for (String item : someArray) {
}
...还有一个额外的好处,那就是还可以了解环路内的电流索引
评论
0
false
NaN
null
undefined
i
(item=someArray[i]) !== undefined
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
console.log(i,j);
}
干净多了......
评论
z.forEach(j => console.log(j));
for (const s of myStringArray) {
(直接回答你的问题:现在你可以了!
大多数其他答案都是正确的,但他们没有提到(在撰写本文时)ECMAScript 6 2015 带来了一种新的迭代机制,即 for。的
循环。
这种新语法是在 JavaScript 中迭代数组的最优雅的方式(只要你不需要迭代索引)。
它目前适用于 Firefox 13+、Chrome 37+,并且它本身不适用于其他浏览器(请参阅下面的浏览器兼容性)。幸运的是,我们有 JavaScript 编译器(例如 Babel),它允许我们今天使用下一代功能。
它也适用于 Node.js(我在 0.12.0 版本上测试了它)。
迭代数组
// You could also use "let" or "const" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) {
console.log(letter);
}
迭代对象数组
const band = [
{firstName : 'John', lastName: 'Lennon'},
{firstName : 'Paul', lastName: 'McCartney'}
];
for(const member of band){
console.log(member.firstName + ' ' + member.lastName);
}
迭代生成器:
(示例摘自 https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...of)
function* fibonacci() { // A generator function
let [prev, curr] = [1, 1];
while (true) {
[prev, curr] = [curr, prev + curr];
yield curr;
}
}
for (const n of fibonacci()) {
console.log(n);
// Truncate the sequence at 1000
if (n >= 1000) {
break;
}
}
兼容性表:http://kangax.github.io/compat-table/es6/#test-for..of_loops
规格:http://wiki.ecmascript.org/doku.php?id=harmony:iterators
}
优化的方法是缓存数组的长度并使用单个变量模式,使用单个关键字初始化所有变量。var
var i, max, myStringArray = ["Hello", "World"];
for (i = 0, max = myStringArray.length; i < max; i++) {
alert(myStringArray[i]);
// Do something
}
如果迭代顺序无关紧要,那么您应该尝试反向循环。它是最快的,因为它减少了开销条件测试,并且递减在一个语句中:
var i,myStringArray = ["item1","item2"];
for (i = myStringArray.length; i--) {
alert(myStringArray[i]);
}
或者更好、更干净地使用 while 循环:
var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
// Do something with fruits[i]
}
最优雅、最快捷的方式
var arr = [1, 2, 3, 1023, 1024];
for (var value; value = arr.pop();) {
value + 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/underscore.js/1.6.0/underscore-min.js"></script>
<script>
Benchmark.prototype.setup = function() {
// Fake function with minimal action on the value
var tmp = 0;
var process = function(value) {
tmp = value; // Hold a reference to the variable (prevent engine optimisation?)
};
// Declare the test Array
var arr = [];
for (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="Hosted by imgur.com" /></a>
评论
好吧,这个怎么样:
for (var key in myStringArray) {
console.log(myStringArray[key]);
}
评论
在 JavaScript 中,有多种方法可以遍历数组。
通用循环:
var i;
for (i = 0; i < substr.length; ++i) {
// Do something with `substr[i]`
}
ES5 的 forEach:
substr.forEach(function(item) {
// Do something with `item`
});
jQuery.each:
jQuery.each(substr, function(index, item) {
// Do something with `item` (or `this` is also `item` if you like)
});
查看此详细信息,或者您也可以检查MDN以在JavaScript中循环访问数组,并使用jQuery检查jQuery。
例如,我在 Firefox 控制台中使用:
[].forEach.call(document.getElementsByTagName('pre'), function(e){
console.log(e);
})
可以使用 querySelectorAll 获取相同的结果
document.querySelectorAll('pre').forEach( (e) => {
console.log(e.textContent);
})
<pre>text 1</pre>
<pre>text 2</pre>
<pre>text 3</pre>
当然,它效率低下,许多人鄙视它,但它是最接近上述内容之一:
var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
// Do something
})
评论
介绍
自从我上大学以来,我就用Java,JavaScript,Pascal,ABAP,PHP,Progress 4GL,C / C++以及其他一些我现在想不起来的语言进行编程。
虽然它们都有自己的语言特性,但这些语言中的每一种都有许多相同的基本概念。这些概念包括过程/函数、-语句、-loops 和 -loops。IF
FOR
WHILE
传统的循环for
传统循环有三个组成部分:for
- 初始化:在第一次执行 look 块之前执行
- 条件:每次在执行循环块之前检查一个条件,如果为 false,则退出循环
- 事后思绪:每次在循环块执行后执行
这三个组件通过符号相互分隔。这三个组件中每个组件的内容都是可选的,这意味着以下内容可能是最小的循环:;
for
for (;;) {
// Do stuff
}
当然,您需要在该 -loop 中包含一个 or 一个 或 一个 ,以使其停止运行。if(condition === true) { break; }
if(condition === true) { return; }
for
但是,通常情况下,初始化用于声明索引,条件用于将该索引与最小值或最大值进行比较,事后用于递增索引:
for (var i = 0, length = 10; i < length; i++) {
console.log(i);
}
使用传统循环遍历数组for
循环访问数组的传统方法是:
for (var i = 0, length = myArray.length; i < length; i++) {
console.log(myArray[i]);
}
或者,如果您更喜欢向后循环,请执行以下操作:
for (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(value);
}
...或者这个......
var i = 0, length = myArray.length;
for (; i < length;) {
console.log(myArray[i]);
i++;
}
...或者这个:
var key = 0, value;
for (; value = myArray[key++];){
console.log(value);
}
无论哪种方法最有效,很大程度上取决于个人品味和您正在实施的特定用例。
请注意,所有浏览器都支持这些变体中的每一个,包括非常非常旧的浏览器!
循环while
循环的另一种方法是循环。要遍历数组,您可以这样做:for
while
var key = 0;
while(value = myArray[key++]){
console.log(value);
}
与传统循环一样,即使是最古老的浏览器也支持循环。for
while
另外,请注意,每隔一段时间,循环都可以重写为循环。例如,上面的循环的行为方式与以下 -loop 完全相同:for
while
for
for(var key = 0; value = myArray[key++];){
console.log(value);
}
For...in
和for...of
在 JavaScript 中,您还可以这样做:
for (i in myArray) {
console.log(myArray[i]);
}
但是,应谨慎使用,因为它在所有情况下的行为都与传统循环不同,并且需要考虑潜在的副作用。请参阅为什么使用“for...in“对于数组迭代是个坏主意?了解更多详情。for
作为...在
,现在还有...的
。以下示例显示了循环和循环之间的区别:for...of
for...in
var myArray = [3, 5, 7];
myArray.foo = "hello";
for (var i in myArray) {
console.log(i); // logs 0, 1, 2, "foo"
}
for (var i of myArray) {
console.log(i); // logs 3, 5, 7
}
此外,您需要考虑任何版本的 Internet Explorer 都不支持(Edge 12+ 支持),并且至少需要 Internet Explorer 10。for...of
for...in
Array.prototype.forEach()
-loops 的替代方法是 Array.prototype.forEach(),
它使用以下语法:for
myArray.forEach(function(value, key, myArray) {
console.log(value);
});
Array.prototype.forEach()
所有现代浏览器以及 Internet Explorer 9 及更高版本都支持。
图书馆
最后,许多实用程序库也有自己的变体。AFAIK,最受欢迎的三个是:foreach
jQuery.each()
,在 jQuery 中:
$.each(myArray, function(key, value) {
console.log(value);
});
_.each(myArray, function(value, key, myArray) {
console.log(value);
});
_.forEach()
,在 Lodash 中:
_.forEach(myArray, function(value, key) {
console.log(value);
});
简短的回答:是的。你可以这样做:
var myArray = ["element1", "element2", "element3", "element4"];
for (i = 0; i < myArray.length; i++) {
console.log(myArray[i]);
}
在浏览器控制台中,您可以看到打印的“element1”、“element2”等内容。
如果你想使用jQuery,它的文档中有一个很好的例子:
$.each([ 52, 97 ], function( index, value ) {
alert( index + ": " + value );
});
最好使用顺序循环:for
for (var i = 0; i < myStringArray.length; i++) {
// Do something
}
评论
在 JavaScript 中,有几种方法可以做到这一点。前两个示例是 JavaScript 示例。第三个使用JavaScript库,即jQuery使用该函数。.each()
var myStringArray = ["hello", "World"];
for(var i in myStringArray) {
alert(myStringArray[i]);
}
var myStringArray = ["hello", "World"];
for (var i=0; i < myStringArray.length; i++) {
alert(myStringArray[i]);
}
var myStringArray = ["hello", "World"];
$.each(myStringArray, function(index, value){
alert(value);
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
评论
for...in
对于类似 Array 的对象,应避免使用
var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
console.log(val, index);
})
var obj = ["one","two","three"];
for(x in obj){
console.log(obj[x]);
}
数组循环:
for(var i = 0; i < things.length; i++){
var thing = things[i];
console.log(thing);
}
对象循环:
for(var prop in obj){
var propValue = obj[prop];
console.log(propValue);
}
在 JavaScript 中,有很多解决方案可以循环数组。
下面的代码是流行的
/** Declare inputs */
const items = ['Hello', 'World']
/** Solution 1. Simple for */
console.log('solution 1. simple for')
for (let i = 0; i < items.length; i++) {
console.log(items[i])
}
console.log()
console.log()
/** Solution 2. Simple while */
console.log('solution 2. simple while')
let i = 0
while (i < items.length) {
console.log(items[i++])
}
console.log()
console.log()
/** Solution 3. forEach*/
console.log('solution 3. forEach')
items.forEach(item => {
console.log(item)
})
console.log()
console.log()
/** Solution 4. for-of*/
console.log('solution 4. for-of')
for (const item of items) {
console.log(item)
}
console.log()
console.log()
在我看来,最好的方法是使用 Array.forEach 函数。如果你不能使用它,我建议从 MDN 获取 polyfill。要使其可用,这当然是 JavaScript 中迭代数组的最安全方法。
因此,正如其他人所建议的那样,这几乎总是您想要的:
var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
sum += n;
});
这确保了在处理数组的范围内所需的任何内容都保持在该范围内,并且您只处理数组的值,而不是对象属性和其他成员,而这正是 in 的作用。for ..
在大多数情况下,使用常规的 C 样式循环是有效的。重要的是要记住,循环中的所有内容都与程序的其余部分共享其作用域,{ } 不会创建新作用域。for
因此:
var sum = 0;
var numbers = [1,11,22,33,44,55,66,77,88,99,111];
for(var i = 0; i<numbers.length; ++i){
sum += numbers[i];
}
alert(i);
将输出“11”——这可能是也可能不是你想要的。
一个有效的 jsFiddle 示例:https://jsfiddle.net/workingClassHacker/pxpv2dh5/7/
是的,你可以在 JavaScript 中使用循环做同样的事情,但不限于此。在 JavaScript 中,有很多方法可以对数组进行循环。想象一下,你下面有这个数组,你想对它做一个循环:
var arr = [1, 2, 3, 4, 5];
这些是解决方案:
1) For 循环
循环是 JavaScript 中循环数组的常用方式,但它不被认为是大型数组的最快解决方案:for
for (var i=0, l=arr.length; i<l; i++) {
console.log(arr[i]);
}
2) While 循环
while 循环被认为是遍历长数组的最快方法,但它在 JavaScript 代码中通常较少使用:
let i=0;
while (arr.length>i) {
console.log(arr[i]);
i++;
}
3) 在 A 做同样的事情时
做,但有一些语法差异,如下所示:do while
while
let i=0;
do {
console.log(arr[i]);
i++;
}
while (arr.length>i);
这些是执行 JavaScript 循环的主要方法,但还有更多方法可以做到这一点。
此外,我们还使用循环来循环 JavaScript 中的对象。for in
还要查看 JavaScript 中数组上的 、 、 等函数。他们可能比使用 和 做事更快、更好。map()
filter()
reduce()
while
for
如果你想了解更多关于 JavaScript 中数组上的异步函数的信息,这是一篇好文章。
函数式编程在 如今的发展世界。这是有充分理由的:功能性 技术可以帮助你编写更多更易于 一目了然地了解、重构和测试。
函数式编程的基石之一是它的特殊用途 列表和列表操作。而这些东西正是 听起来像是:事物的阵列,以及你对它们所做的事情。 但是功能性思维方式对待他们的方式与你略有不同 可能会预料到。
本文将仔细研究我喜欢称之为“大 三“列表操作:map、filter 和 reduce。包住你的头 围绕这三个功能是迈向能够 编写干净的功能代码,并打开通往 强大的函数式和反应式编程技术。
这也意味着你再也不用写for循环了。
似乎列出了所有变体,除了 lodash:forEach
_.forEach([1, 2], (value) => {
console.log(value);
});
只需一个简单的单行解决方案:
arr = ["table", "chair"];
// Solution
arr.map((e) => {
console.log(e);
return e;
});
评论
.forEach()
return e;
map
map
在 JavaScript 中以函数式编程方式遍历数组的一些用例:
1. 只需遍历一个数组
const myArray = [{x:100}, {x:200}, {x:300}];
myArray.forEach((element, index, array) => {
console.log(element.x); // 100, 200, 300
console.log(index); // 0, 1, 2
console.log(array); // same myArray object 3 times
});
注意:严格来说,Array.prototype.forEach() 不是一个函数方式,因为它作为输入参数的函数不应该返回一个值,因此不能将其视为纯函数。
2. 检查数组中的任何元素是否通过测试
const people = [
{name: 'John', age: 23},
{name: 'Andrew', age: 3},
{name: 'Peter', age: 8},
{name: 'Hanna', age: 14},
{name: 'Adam', age: 37}];
const anyAdult = people.some(person => person.age >= 18);
console.log(anyAdult); // true
3. 转换为新数组
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray= myArray.map(element => element.x);
console.log(newArray); // [100, 200, 300]
注意:map() 方法创建一个新数组,其中包含在调用数组中的每个元素上调用提供的函数的结果。
4. 总结特定属性,并计算其平均值
const myArray = [{x:100}, {x:200}, {x:300}];
const sum = myArray.map(element => element.x).reduce((a, b) => a + b, 0);
console.log(sum); // 600 = 0 + 100 + 200 + 300
const average = sum / myArray.length;
console.log(average); // 200
5. 在原始数组的基础上创建一个新数组,但不对其进行修改
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray= myArray.map(element => {
return {
...element,
x: element.x * 2
};
});
console.log(myArray); // [100, 200, 300]
console.log(newArray); // [200, 400, 600]
6.统计每个类别的数量
const people = [
{name: 'John', group: 'A'},
{name: 'Andrew', group: 'C'},
{name: 'Peter', group: 'A'},
{name: 'James', group: 'B'},
{name: 'Hanna', group: 'A'},
{name: 'Adam', group: 'B'}];
const groupInfo = people.reduce((groups, person) => {
const {A = 0, B = 0, C = 0} = groups;
if (person.group === 'A') {
return {...groups, A: A + 1};
} else if (person.group === 'B') {
return {...groups, B: B + 1};
} else {
return {...groups, C: C + 1};
}
}, {});
console.log(groupInfo); // {A: 3, C: 1, B: 2}
7. 根据特定条件检索数组的子集
const myArray = [{x:100}, {x:200}, {x:300}];
const newArray = myArray.filter(element => element.x > 250);
console.log(newArray); // [{x:300}]
注意:filter() 方法创建一个新数组,其中包含通过所提供函数实现的测试的所有元素。
8. 对数组进行排序
const people = [
{ name: "John", age: 21 },
{ name: "Peter", age: 31 },
{ name: "Andrew", age: 29 },
{ name: "Thomas", age: 25 }
];
let sortByAge = people.sort(function (p1, p2) {
return p1.age - p2.age;
});
console.log(sortByAge);
9. 在数组中查找元素
const people = [ {name: "john", age:23},
{name: "john", age:43},
{name: "jim", age:101},
{name: "bob", age:67} ];
const john = people.find(person => person.name === 'john');
console.log(john);
Array.prototype.find() 方法返回数组中满足所提供测试函数的第一个元素的值。
引用
- Array.prototype.some()
- Array.prototype.forEach()
- 数组.prototype.map()
- 数组.prototype.filter()
- 数组.prototype.sort()
- Spread 语法
- 数组.prototype.find()
如果有人对可用于 Array 迭代的多种机制的性能方面感兴趣,我准备了以下 JSPerf 测试:
https://jsperf.com/fastest-array-iterator
结果:
传统的迭代器是迄今为止最快的方法,尤其是在缓存数组长度的情况下。for()
let arr = [1,2,3,4,5];
for(let i=0, size=arr.length; i<size; i++){
// Do something
}
和 方法是最慢的近似值,可能是函数调用开销的结果。Array.prototype.forEach()
Array.prototype.map()
评论
i = i +1
i++
var array = ['hai', 'hello', 'how', 'are', 'you']
$(document).ready(function () {
$('#clickButton').click(function () {
for (var i = 0; i < array.length; i++) {
alert(array[i])
}
})
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js"></script>
<input id="clickButton" value="click Me" type="button"/>
<div id="show"></div>
评论
正式的(也许是旧的)方式是:Array.prototype.forEach(...)
var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach(function(item, index, _) {
console.log("[" + index + "] = '" + item + "'");
});
评论
深晦
let 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 个测试:
- small - 对于 2 个元素数组(如 OP) - 你可以在这里运行它
- medium - 用于 10K 元素数组和 - 您可以在此处运行它
- big - 对于 100K 元素数组 - 你可以在这里运行它
以下代码片段显示了测试中使用的代码。
function A(a) {
let r=0;
while(a.length) r+= a.shift().length;
return r;
}
function B(a) {
let r=0;
for(i in a) r+= a[i].length;
return r;
}
function C(a) {
let r=0;
for(x of a) r+= x.length;
return r;
}
function D(a) {
let r=0;
for (i=0; i<a.length; ++i) r+= a[i].length;
return r;
}
function E(a) {
let r=0;
a.forEach(x=> r+= x.length);
return r;
}
let arr= ["Hello", "World!"];
[A,B,C,D,E].forEach(f => console.log(`${f.name}: ${f([...arr])}`))
以下是中型阵列的 Chrome 示例结果:
评论
while(a.length) { console.log(a.shift()); }
for(var i = 0; i < a.length; i++) { console.log(a[i]); }
JavaScript 中的数组遍历备忘单
给定一个数组,您可以通过以下多种方式之一遍历它。
1. 经典的for
循环
const myArray = ['Hello', 'World'];
for (let i = 0; i < myArray.length; i++) {
console.log(myArray[i]);
}
2. 为了...之
const myArray = ['Hello', 'World'];
for (const item of myArray) {
console.log(item);
}
const myArray = ['Hello', 'World'];
myArray.forEach(item => {
console.log(item);
});
4. while
循环
const myArray = ['Hello', 'World'];
let i = 0;
while (i < myArray.length) {
console.log(myArray[i]);
i++;
}
5. 做...while
循环
const myArray = ['Hello', 'World'];
let i = 0;
do {
console.log(myArray[i]);
i++;
} while (i < myArray.length);
6. 队列样式
const myArray = ['Hello', 'World'];
while (myArray.length) {
console.log(myArray.shift());
}
7. 堆栈样式
注意:在此列表中,列表是反向打印的。
const myArray = ['Hello', 'World'];
while (myArray.length) {
console.log(myArray.pop());
}
评论
//Make array
var array = ["1","2","3","4","5","6","7","8","9","10"]
//Loop
for(var i = 0; i < array.length; i++){
console.log((i+1) + " --> " + array[i])
}
对于 的 实际数字,如果需要,需要更改为 或 。
希望这有帮助。i
(i+1)
i
(i)
6 种不同的方法来遍历数组
您可以通过许多不同的方法遍历数组。我从上到下整理了我最喜欢的 6 种方法。
1.使用 JavaScript for 循环
当它只是循环遍历一个数组时,循环是我的首选。for
let array = [1, 2, 3, 4, 5];
for (let i = 0; i < array.length; i++) {
console.log(array[i]);
}
2.使用 forEach 循环
forEach
loop 是一种遍历数组的现代方法。此外,它还提供了更大的灵活性和对数组和元素的控制。
let array = [1, 2, 3, 4, 5];
array.forEach((element) => {
console.log(element);
});
3.用于...之
for...of
loop 使您可以直接访问数组元素。
let array = [1, 2, 3, 4, 5];
for (let element of array) {
console.log(element);
}
4.用于...在循环中
for...in
为您提供一个键,您可以使用该键访问数组元素。
let array = [1, 2, 3, 4, 5];
for(let index in array){
console.log(array[index]);
}
5.使用 while 循环
while loop 也可用于遍历数组。
let array = [1, 2, 3, 4, 5];
let length = array.length;
while(length > 0){
console.log(array[array.length - length]);
length--;
}
6.使用do...while 循环
同样,我使用循环do...while
let array = [1, 2, 3, 4, 5];
let length = array.length;
do {
console.log(array[array.length - length]);
length--;
}
while (length > 0)
数组迭代有 4 种方式:
// 1: for
for (let i = 0; i < arr.length; ++i) {
console.log(arr[i]);
}
// 2: forEach
arr.forEach((v, i) => console.log(v));
// 3: for in
for (let i in arr) {
console.log(arr[i]);
}
// 4: for of
for (const v of arr) {
console.log(v);
}
摘要:1 和 3 解决方案创建额外的变量,2 - 创建额外的函数上下文。最好的方式是第 4 个 - “为了”。
评论
考虑一下:
const ITEMS = ['One','Two','Three']
let item=-1
//Then, you get looping with every call of:
ITEMS[item=item==ITEMS.length-1?0:item+1]
在 javascript 中有多种方法可以做到这一点。以下是处理数组的常用方法。
方法1:
const students = ["Arun","Jos","John","Kiran"]
for (var index = 0; index < students.length; index++) {
console.log(students[index]);
}
方法2:
students.forEach((student, index) => console.log(student));
方法3:
for (const student of students) {
console.log(student);
}
这个答案提供了循环和数组函数的替代方法,用于遍历数组。
在某些情况下,使用递归实现而不是传统的循环和回调是有意义的。特别是,如果您必须使用多个数组或嵌套数组。您可以避免编写嵌套循环来访问来自多个数组的数据。我还发现这段代码更易于阅读和编写。
/**
array is the array your wish to iterate.
response is what you want to return.
index increments each time the function calls itself.
**/
const iterateArray = (array = [], response = [], index = 0) => {
const data = array[index]
// If this condition is met. The function returns and stops calling itself.
if (!data) {
return response
}
// Do work...
response.push("String 1")
response.push("String 2")
// Do more work...
// THE FUNCTION CALLS ITSELF
iterateArray(data, response, index+=1)
}
const mainFunction = () => {
const text = ["qwerty", "poiuyt", "zxcvb"]
// Call the recursive function
const finalText = iterateArray(text)
console.log("Final Text: ", finalText()
}
假设数组被传递给包含的对象而不是字符串。每个对象都包含另一个数组。您必须运行嵌套循环才能访问内部数组,但如果以递归方式迭代,则不会。iterateArray
你也可以做出承诺。iterateArray
const iterateArray = (array = [], response = []) =>
new Promise(async (resolve, reject) => {
const data = array.shift()
// If this condition is met, the function returns and stops calling itself.
if (!data) {
return resolve(response)
}
// Do work here...
const apiRequestData = data.innerArray.find((item) => {
item.id === data.sub_id
})
if (apiRequestData) {
try {
const axiosResponse = await axios.post(
"http://example.com",
apiRequestData
)
if (axiosResponse.status === 200) {
response.push(apiRequestData)
} else {
return reject("Data not found")
}
} catch (error) {
reject(error)
}
} else {
return reject("Data not found")
}
// THE FUNCTION RESOLVES AND CALLS ITSELF
resolve(iterateArray(data, response))
})
评论
for-in
in
of
forEach