繁体   English   中英

循环遍历 JavaScript 中的一个数组

[英]Loop through an array in JavaScript

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

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray) {
    // Do something
}

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

三个主要选项:

  1. for (var i = 0; i < xs.length; i++) { console.log(xs[i]); }
  2. xs.forEach((x, i) => console.log(x));
  3. 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 }

优点

  • 适用于各种环境
  • 您可以使用breakcontinue流控制语句

缺点

  • 太冗长
  • 至关重要的
  • 容易出现一个错误(有时也称为栅栏柱错误

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 });

正确使用reduce

 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方法允许您仅枚举自己的属性 就是这样,只有对象物理具有的属性,没有继承的属性。

我建议您阅读以下文章:

是的,假设您的实现包括ECMAScript 2015 (“Harmony”版本)中引入的for ... of功能...这是一个非常安全的假设。

它是这样工作的:

// 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 中的数组实际上可能存储的项目数可能没有它的length报告的那么多; 该报告的数字仅比存储值的最高索引大一。 如果数组包含的元素少于其长度所指示的元素,则称其为sparse 例如,拥有一个仅在索引 3、12 和 247 处包含项目的数组是完全合法的; 这种数组的length报告为 248,尽管它实际上只存储了 3 个值。 如果您尝试访问任何其他索引处的项目,则该数组将在那里出现undefined的值。 所以当你想“遍历”一个数组时,你有一个问题要回答:你是想遍历它的长度所指示的整个范围并为任何缺失的元素处理undefined s,还是只想处理元素实际存在? 这两种方法都有很多应用。 这仅取决于您使用数组的目的。

如果您使用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 ...
} );

for ... of不同, .forEach仅调用数组中实际存在的元素的函数。 如果传递我们假设的具有三个元素且长度为 248 的数组,它只会调用该函数 3 次,而不是 248 次。 它还区分缺失元素和实际设置为undefined的元素; 对于后者,它仍然会调用函数,传递undefined作为参数。 如果这是您想要处理稀疏数组的方式,那么即使您的解释器for ... of.forEach也可能是可行的方法。

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

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表达式)可以显着提高性能,因为它每次都会跳过属性查找; 在我的机器上使用 Rhino,加速是 43%。

您可能会在循环初始化子句中看到长度缓存,如下所示:

var i, len, myStringArray = [ "Hello", "World" ];
for (len = myStringArray.length, i=0; i<len; ++i) {

如果需要,显式计数循环还意味着您可以访问每个值的索引。 索引也作为额外参数传递给您传递给forEach的函数,因此您也可以通过这种方式访问​​它:

myStringArray.forEach( function(s, i) {
   // ... do something with s and i ...
});

for ... of不会为您提供与每个对象关联的索引,但只要您要迭代的对象实际上是一个Arrayfor .. of适用于可能没有此方法的其他可迭代类型),您可以使用Array#entries方法将其更改为 [index, item] 对的数组,然后对其进行迭代:

for (const [i, s] of myStringArray.entries()) {
  // ... do something with s and i ...
}

其他人提到的for ... in语法是用于循环对象的属性; 由于 JavaScript 中的 Array 只是一个具有数字属性名称的对象(以及一个自动更新的length属性),因此理论上您可以使用它遍历 Array。 但问题是它并不局限于数字属性值(请记住,即使方法实际上只是其值为闭包的属性),也不能保证按数字顺序迭代那些。 因此, for ... in语法应该用于遍历数组。

您可以使用map ,这是一种函数式编程技术,在PythonHaskell等其他语言中也可用。

[1,2,3,4].map( function(item) {
     alert(item);
})

一般语法是:

array.map(func)

通常func会接受一个参数,它是数组的一项。 但在 JavaScript 的情况下,它可以采用第二个参数,即项目的索引,以及第三个参数,即数组本身。

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

for (const s of myStringArray) {

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

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

这种新语法是在 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

}

在 JavaScript 中,不建议使用 for-in 循环遍历 Array,但最好使用for循环,例如:

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

它也经过优化(“缓存”数组长度)。 如果您想了解更多信息, 请阅读我关于该主题的帖子

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

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

Mozilla Labs 发布了他们和WebKit都使用的算法,因此您可以自己添加它们。

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

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

如果有任何通过测试,则some返回 true。

forEach在每个数组成员上运行一个函数并且不返回任何内容。

map类似于 forEach,但它返回一个包含每个元素的操作结果的数组。

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

忽略它,直到你需要它。

indexOflastIndexOf找到与其参数完全匹配的第一个或最后一个元素的适当位置。

(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;
})();

介绍

自从我上大学以来,我已经使用 Java、JavaScript、Pascal、 ABAP 、PHP、 Progress 4GL 、C/C++ 以及一些我现在想不出的其他语言进行编程。

虽然它们都有自己的语言特性,但这些语言中的每一种都有许多相同的基本概念。 这些概念包括过程/函数、 IF语句、 FOR循环和WHILE循环。


传统for循环

传统for循环包含三个组件:

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

这三个组件之间用;隔开。 象征。 这三个组件中的每一个的内容都是可选的,这意味着以下是尽可能少for循环:

for (;;) {
    // Do stuff
}

当然,您需要包含一个if(condition === true) { break; } if(condition === true) { break; }if(condition === true) { return; } if(condition === true) { return; }在那个for -loop 里面的某个地方让它停止运行。

但是,通常初始化用于声明索引,条件用于将该索引与最小值或最大值进行比较,事后考虑用于增加索引:

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循环。

另外,请注意,每个 while 循环都可以重写为for循环。 例如,上面的while循环与for循环的行为方式完全相同:

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

For...infor...of

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

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

然而,这应该小心使用,因为在所有情况下它的行为都与传统for循环不同,并且需要考虑潜在的副作用。 请参阅为什么使用“for...in”进行数组迭代是一个坏主意? 更多细节。

作为for...in的替代方案,现在还有for...of 以下示例显示了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 支持for...ofEdge 12+支持)并且for...in至少需要 Internet Explorer 10。


Array.prototype.forEach()

for循环的替代方法是Array.prototype.forEach() ,它使用以下语法:

myArray.forEach(function(value, key, myArray) {
    console.log(value);
});

所有现代浏览器以及 Internet Explorer 9 及更高版本都支持Array.prototype.forEach()


图书馆

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

jQuery.each() ,在jQuery中:

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

_.each() ,在Underscore.js中:

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

_.forEach() ,在Lodash中:

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

6种不同的方法来遍历数组

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

1.使用for循环

当它只是简单地遍历一个数组时, for循环是我的首选。

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

2.使用forEach循环

forEach循环是一种遍历数组的现代方式。 此外,它提供了更多的灵活性和对数组和元素的控制。

 let array = [1, 2, 3, 4, 5]; array.forEach((element) => { console.log(element); });

3. 使用 for...of

for...of循环使您可以直接访问数组元素。

 let array = [1, 2, 3, 4, 5]; for (let element of array) { console.log(element); }

4. 使用 for...in 循环

for...in为您提供一个可以访问数组元素的键。

 let array = [1, 2, 3, 4, 5]; for(let index in array){ console.log(array[index]); }

5.使用while循环

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

 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)

使用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]);
}

它记录:'一','二','三'

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

如果您想要一种简洁的方式来编写快速循环,并且可以反向迭代:

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 中删除项目。

在 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() 方法返回数组中满足提供的测试函数的第一个元素的值。

参考

的,你可以在 JavaScript 中使用循环来做同样的事情,但不限于此。 有很多方法可以在 JavaScript 中对数组进行循环。 假设您在下面有这个数组,并且您想对其进行循环:

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

这些是解决方案:

1)for循环

for循环是 JavaScript 中遍历数组的常用方法,但它不被认为是大型数组的最快解决方案:

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)做一会儿
do while while while 执行相同的操作,但语法差异如下:

let i=0;
do {
  console.log(arr[i]);
  i++;
}
while (arr.length>i);

这些是执行 JavaScript 循环的主要方法,但还有其他几种方法可以做到这一点。

我们还使用for in循环来循环 JavaScript 中的对象。

另请查看 JavaScript 中数组上的map()filter()reduce()等函数。 他们可能比使用whilefor更快更好地做事。

如果您想了解更多关于 JavaScript 中数组上的异步函数的信息,这是一篇很好的文章。

这些天来,函数式编程在开发界引起了轰动。 并且有充分的理由:函数式技术可以帮助您编写更易于一目了然、重构和测试的声明性代码。

函数式编程的基石之一是它对列表和列表操作的特殊使用。 而这些东西正是它们听起来的样子:一系列的东西,以及你对它们所做的事情。 但是功能性思维方式对待它们的方式与您预期的有所不同。

本文将仔细研究我喜欢称之为“三巨头”的列表操作:map、filter 和 reduce。 围绕这三个函数展开思考是朝着编写干净的函数式代码迈出的重要一步,并为函数式和反应式编程的强大技术打开了大门。

这也意味着您永远不必再次编写 for 循环。

在此处阅读更多>>:

有一种方法可以做到这一点,您的循环中的隐式范围非常小,并消除了额外的变量。

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
}

现代浏览器都支持迭代器方法forEachmapreducefilterArray 原型上的许多其他方法。

我强烈推荐使用Underscore.js库。 它为您提供了可用于迭代数组/集合的各种函数。

例如:

_.each([1, 2, 3], function(num){ alert(num); });
=> alerts each number in turn...

在 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.每个:

jQuery.each(substr, function(index, item) {
    // Do something with `item` (or `this` is also `item` if you like)
});

看看这个以获取详细信息,或者您也可以检查MDN以在 JavaScript 中循环遍历数组并使用 jQuery 检查每个 jQuery

数组循环:

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);
}

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

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

性能结果

结果:

传统for()迭代器是迄今为止最快的方法,尤其是与数组长度 cached一起使用时。

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()方法是最慢的近似值,可能是函数调用开销的结果。

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

给定一个数组:

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 等,则循环将过早中断。 同样在实践中,这对我来说几乎不是问题,但要牢记这一点,这使得在使用它之前要考虑一个循环......这可能会让某些人失去资格:)

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

  • 写的很短
  • 无需访问(更不用说缓存)长度属性
  • 要访问的项目在您选择的名称下的循环主体内自动定义。
  • 非常自然地与 array.push 和 array.splice 结合使用数组,如列表/堆栈

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

对我来说,这个结构最接近地模拟了我喜欢的 Java 5 语法:

for (String item : someArray) {
}

...还有一个额外的好处是还知道循环内的当前索引

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

从文档中:

jQuery.each( collection, callback(indexInArray, valueOfElement) )

返回:对象

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

$.each()函数与$(selector).each() ,后者用于以独占方式迭代 jQuery 对象。 $.each()函数可用于迭代任何集合,无论是映射(JavaScript 对象)还是数组。 在数组的情况下,回调每次都会传递一个数组索引和一个对应的数组值。 (该值也可以通过this关键字访问,但 JavaScript 将始终将this值包装为一个Object ,即使它是一个简单的字符串或数字值。)该方法返回其第一个参数,即被迭代的对象。

数组迭代有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 - "for of"

深奥的可变方式

 let a= ["Hello", "World"]; while(a.length) { console.log( a.shift() ); }

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

for (var i in array) if (array.hasOwnProperty(i)) {
    // Do something with array[i]
}

但它仍然会遍历自定义属性。

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

如果想要遍历稀疏数组,应该for (var i = 0; i < array.length; i++) if (i in array)array.forEaches5shim

最优雅快捷的方式

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>

优化的方法是缓存数组的长度并使用单变量模式,使用单个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]
}

在 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>

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

 $.each([ 52, 97 ], function( index, value ) {
      alert( index + ": " + value );
 });

在 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 中迭代数组的最安全方法。

Array.prototype.forEach()

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

var numbers = [1,11,22,33,44,55,66,77,88,99,111];
var sum = 0;
numbers.forEach(function(n){
  sum += n;
});

这可确保您在处理数组范围内所需的任何内容都保持在该范围内,并且您只处理数组的值,而不是对象属性和其他成员,这就是for .. in 所做的。

在大多数情况下,使用常规 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/

它不是 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 }

例如,我在 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>

正式的(也许是旧的)方式是Array.prototype.forEach(...)

var arr = ["apple", "banana", "cherry", "mango"];
arr.forEach(function(item, index, _) {
   console.log("[" + index + "] = '" + item + "'");
});
var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

干净多了...

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

String[] myStringArray = {"Hello", "World"};
for (String s : myStringArray)
{
    // Do something
}

您可以在JavaScript中做同样的事情吗?

//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)
希望这有帮助。

似乎列出了所有变体,除了lodash 的forEach

_.forEach([1, 2], (value) => {
  console.log(value);
});

只是一个简单的单线解决方案:

 arr = ["table", "chair"]; // Solution arr.map((e) => { console.log(e); return e; }); 

嗯,这个怎么样:

for (var key in myStringArray) {
    console.log(myStringArray[key]);
}

当然,它效率低下,很多人都鄙视它,但这是最接近上述方法之一:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})
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循环:

for (var i = 0; i < myStringArray.length; i++) {
    // Do something
}

JavaScript 中的数组遍历备忘单

给定一个数组,您可以通过以下多种方式之一遍历它。

1.经典for循环

 const myArray = ['Hello', 'World']; for (let i = 0; i < myArray.length; i++) { console.log(myArray[i]); }

2. for...of

 const myArray = ['Hello', 'World']; for (const item of myArray) { console.log(item); }

3. Array.prototype.forEach()

 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. do...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()); }

 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>

考虑一下:

var item = ['One','Two','Three'] var item=-1

然后,您会在每次调用时循环:

项目[项目=项目==项目.length-1?0:项目+1]

在 javascript 中有多种方法可以做到这一点。 以下是处理arrays的常用方法。

方法一:

const students = ["Arun","Jos","John","Kiran"]
for (var index = 0; index < students.length; index++) {
  console.log(students[index]);
}

方法二:

students.forEach((student, index) => console.log(student));

方法三:

for (const student of students) {
      console.log(student);
}
  

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM