在JavaScript中循环遍历数组

Mark Szymanski 2651 javascript arrays loops for-loop

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

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

你能用JavaScript做同样的事吗?

CMS.. 3268

使用顺序for循环:

var myStringArray = ["Hello","World"];
    var arrayLength = myStringArray.length;
    for (var i = 0; i < arrayLength; i++) {
        console.log(myStringArray[i]);
        //Do something
    }

@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方法允许您仅枚举自己的属性,即它,只有对象物理上具有的属性,没有继承属性.

我建议你阅读以下文章:

  • 为什么要投票?对于类似数组的对象,应该*避免`for ... in`! (179认同)
  • 这就是原因(由CMS自己)http://stackoverflow.com/questions/1885317/strange-behavior-in-javascript-enhanced-for-in-loop/1885365#1885365 (16认同)
  • @DoubleGras,我认为这是一个不为大家所共享的意见.请参阅:http://stackoverflow.com/questions/5752906/is-reading-the-length-property-of-an-array-really-that-expensive-an-operation或https://groups.google.com/论坛/?fromgroups#!话题/ jsmentors/Umwd3sz - 人民军%5B1-25%5D (14认同)
  • @StijndeWitt不,因为如果你的数组中有任何_"falsey"_值,那就会中断:`false`,`undefined`,`0`,````,`NaN`. (13认同)
  • http://jsperf.com/caching-array-length/4这是一个测试,看看是否值得在Javascript循环中缓存数组的长度 (5认同)
  • 为什么这对于someArray.forEach(function(item){})更好,它应该有这么多的upvotes? (5认同)
  • 有人认为你需要缓存长度...请看我的答案,你甚至不需要一次访问它,更不用说缓存它了:for(var i = 0,item; item = myStringArray [i]; i ++){/*在这里使用项目*/} (2认同)
  • 我没有考虑缓存长度的唯一原因是在循环进行时数组是否发生了变化 (2认同)

Mark Reed.. 998

是的,假设您的实现包括ECMAScript 2015中引入的for... of特性("Harmony"版本)......这些天是一个非常安全的假设.

它的工作原理如下:

// REQUIRES ECMASCRIPT 2015+
var s, myStringArray = ["Hello", "World"];
for (s of myStringArray) {
  // ... do something with s ...
}

或者更好的是,由于2015年的ECMAScript还通过提供块作用域的变量letconst:

// REQUIRES ECMASCRIPT 2015+
const myStringArray = ["Hello", "World"];
for (const s of myStringArray) {
  // ... do something with s ...
}
// s is no longer defined here

然而,一些JavaScript开发人员仍然在一个尚未出现的环境中工作 - 特别是如果编写代码在Web浏览器中运行,那么网站开发人员通常无法确定他们的客户将使用哪种浏览器/版本.

如果您可以假设JavaScript解释器符合以前版本的ECMAScript规范(例如,排除了9之前的Internet Explorer版本),那么您可以使用forEach迭代器方法而不是循环.在这种情况下,您传递一个要在数组中的每个项目上调用的函数:

var myStringArray = [ "Hello", "World" ];
myStringArray.forEach( function(s) { 
     // ... do something with s ...
} );

但是,如果即使这样做太多了,并且您想要在所有版本的JavaScript 中都能运行的东西,那么您必须使用显式计数循环.最安全的版本,正确处理稀疏数组,如下所示:

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) {

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

  • 请注意,某些解释器(例如V8)将自动缓存数组的长度_if_代码被调用足够多次,并且它检测到循环未修改长度.虽然缓存长度仍然很好,但是当您的代码被调用足够多次以实际产生差异时,它可能无法提供速度提升. (21认同)
  • @ mark-reed你可以解释为什么你在你的例子中使用了`i in myStringArray`吗?这怎么可能是假的? (2认同)
  • @DenisV:假.`一个= [1,2,3,4]; 删除一个[2]; for(j in a){console.log(j); 输出0,1,3和4.`a.length`仍然是5. (2认同)
  • @GrijeshChauhan - 对.例如,IE到版本8不支持它.见[this question](http://stackoverflow.com/questions/156696/which-web-browsers-natively-support-array-foreach). (2认同)

hasen.. 415

您可以使用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.

  • 使用`Array.forEach`可能更好地实现了这个特定的例子.`map`用于生成新数组. (91认同)
  • @hasen,`Array.prototype.map`方法是ECMAScript第5版标准的一部分,尚未在所有实现上可用(例如IE缺少它),也用于*迭代*在数组上我认为[`Array .prototype.forEach`](https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Objects/Array/ForEach)方法更加*语义*正确...也请不要建议for-in语句,请参阅我的答案了解更多详情:) (21认同)
  • 不,但它可以更强大.看看这个:http://www.joelonsoftware.com/items/2006/08/01.html (7认同)
  • `forEach`和`map`之间的区别在于前者不返回迭代的结果.`map`(有时也称为`collect`,但与`apply`非常不同)明确用于将数组的每个元素转换为相应的结果; 它是1对1*映射*,因此得名.它是整个操作系列的一部分,包括`reduce`(从整个数组产生单个结果)和`filter`(产生原始数组的子集)等等.而'forEach`只对每个元素做了一些事情,而未指定语义. (3认同)
  • Downvote是因为如果你实际上并没有映射某些内容,那么使用[..map]会产生误导.[] .forEach具有语义意义,并​​且还将相同的三个参数传递给函数. (3认同)
  • 如果您查看CMS提供的链接,那么您可以在本机不支持它的浏览器中使用该实现. (2认同)

sebarmeli.. 107

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

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

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

  • `++ i`是一个古老的学校优化,现代编译器为你做了很久以前的for循环:) http://stackoverflow.com/a/1547433/1033348 (13认同)
  • 你必须小心使用这个循环.我开始使用它并且因为我犯了一个错误而难以追踪错误.如果你嵌套这样的两个循环:http://jsfiddle.net/KQwmL/1/.您必须小心在两个循环中以不同的方式命名var len,否则第二个循环将覆盖第一个len. (5认同)
  • myArray.forEach(function(obj){}); 仍然是最好的 (2认同)

Marlon Berna.. 101

for(var s of myStringArray){

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

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

这种新语法是在javascript中迭代数组的最优雅方式(只要您不需要迭代索引),但浏览器尚未广泛支持它.

它目前适用于Firefox 13 +,Chrome 37+,它本身不能与其他浏览器一起使用(请参阅下面的浏览器兼容性).幸运的是,我们有JS编译器(例如Babel),它们允许我们今天使用下一代功能.

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

迭代一个数组

// You could also use "let" instead of "var" for block scope.
for (var letter of ["a", "b", "c"]) { 
   console.log(letter); 
}

迭代一个对象数组

var band = [
  {firstName : 'John', lastName: 'Lennon'}, 
  {firstName : 'Paul', lastName: 'McCartney'}
];

for(var 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 (let n of fibonacci()) {
  console.log(n);
  // truncate the sequence at 1000
  if (n >= 1000) {
    break;
  }
}

兼容性表: http ://kangax.github.io/es5-compat-table/es6/#For..of循环

规格: http ://wiki.ecmascript.org/doku.php?id = ethmony : iterators

}


kennebec.. 84

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

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

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

filter返回满足某些条件或测试的项数组.

如果每个阵列成员通过该测试返回true.

一些返回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;
})();


Timo Huovine.. 62

使用while循环...

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

日志:'one','two','three'

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

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'

参考:http: //www.sitepoint.com/google-closure-how-not-to-write-javascript/

  • 如果任何数组元素是假的,那么"while"语法的第一个例子将不起作用. (17认同)
  • ...而这个while循环相当于:for(var i = 0,item; item = items [i]; i ++),它不需要事先声明索引和项变量... (2认同)

John Slegers.. 52

介绍

从大学毕业后,我编写了Java,JavaScript,Pascal,ABAP,PHP,Progress 4GL,C/C++以及其他一些我现在想不到的语言.

虽然它们都有自己的语言特性,但每种语言都有许多相同的基本概念.这些概念包括过程/函数,IF-statements,FOR-loops和WHILE-loops.


传统的for循环

传统的for循环有三个组成部分:

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

这三个组件通过;符号彼此分开.这三个组件中的每个组件的内容都是可选的,这意味着以下是for可能的最小循环:

for (;;) {
    // Do stuff
}

当然,你需要在-loop中包含一个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即使是最古老的浏览器也支持循环.

另请注意,每个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...of(Edge 12+支持),并且for...in至少需要Internet Explorer 10.


Array.prototype.forEach()

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

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

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


图书馆

最后,许多实用程序库也有自己的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.js:

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


Phrogz.. 36

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

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

  • 对于那些没有得到如此巧妙的人:首先评估i--表达式并允许循环在不是伪造时继续...然后计数器递减.一旦我变为零,它就会突破循环,因为零是Javascript中的虚假值. (16认同)
  • falsish?你的意思是假的.让我们都坚持正确的术语,以避免混淆;) (5认同)
  • 我已经看到了我认为是大师的人所使用的伪造一词.如果它对他们来说足够好,对我来说就足够了.同样令人失望的是看到我的评论实际上是ontopic并添加了解释/洞察得到0赞成票,但是我评论中对一个术语的评论得到的评论得到4.好吧我只是优先考虑的问题. (4认同)

Yuci.. 28

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

参考


Gabriel.. 26

有一种方法可以在循环中具有非常小的隐式范围并且消除额外的变量.

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
}

现代浏览器都支持迭代方法forEach,map,reduce,filter和对其他方法主机数组原型.

  • 请注意,如果代码被调用足够多次并且它检测到循环未修改长度,则某些解释器(例如V8)将自动缓存数组的长度. (3认同)

RizN81.. 26

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

  • 令人遗憾的是ES5 forEach并不是最重要的答案,因为它最符合OP的要求. (4认同)

Andrew Thoms.. 25

我完全建议使用underscore.js库.它为您提供了各种可用于迭代数组/集合的函数.

例如:

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

  • 对于这个问题的新发现者,我只想指出[Lo-Dash](http://lodash.com/),这是Underscore的精神继承者,它在很多方面对其进行了改进. (7认同)
  • 如果[ECMA-262](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach#Polyfill)添加了`forEach`方法,为什么要使用`underscore` .本机代码总是更好. (3认同)

bzim.. 24

数组循环:

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


Alireza.. 22

是的,您可以在JavaScript中使用循环执行相同的操作,但不限于此,在JavaScrip中执行循环数组的许多方法,假设您在下面有这个数组,并且您想对它进行循环:

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

虽然循环被认为是循环遍历长数组的最快方法,但通常在JavaScript中使用较少:

let i=0;

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

3)做同时
做同样的事情,但有一些语法差异如下:

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

这些是进行javascript循环的主要方法,但是还有更多的方法可以做到这一点.

我们还使用for in循环来循环javascript中的对象.

另外,也要看看map(),filter(),reduce()等功能于JavaScript的数组.他们可能比使用while和更快更好地做事for.

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

如今,功能编程在开发领域引起了轰动.并且有充分的理由:功能技术可以帮助您编写更多的声明性代码,一目了然,重构和测试更容易理解.

函数式编程的基石之一是它对列表和列表操作的特殊使用.而那些东西正是它们的声音:事物的数组,以及你对它们所做的事情.但功能性思维方式对待它们的方式与您预期的有所不同.

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

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

阅读更多>> 这里:


justingordon.. 19

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

从文档:

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

返回: 对象

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

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

  • jQuery的一切? (7认同)
  • 同意例外.不要低估额外依赖的影响.除了代码中已经大量使用jQuery之外,我会建议不要这样做. (6认同)

colxi.. 18

如果有人对可用于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()方法是最慢的近似值,可能作为的结果,函数调用的开销


Stijn de Wit.. 16

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

给定一个数组:

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中使用稀疏数组......在这种情况下,使用对象作为map/hashtable通常要容易得多.如果你有一个稀疏数组,并希望循环遍历0 .. length-1,你需要for(var i = 0; i <someArray.length; ++ i)构造,但是你仍需要一个if循环以检查当前索引处的元素是否实际定义.

此外,正如CMS在下面的注释中提到的那样,您只能在不包含任何伪造值的数组上使用它.示例中的字符串数组有效,但如果您有空字符串,或者数字为0或NaN等,则循环将过早中断.再次在实践中,这对我来说几乎不是问题,但是要记住这一点,这使得在使用它之前需要考虑这个循环...这可能会使某些人取消它的资格:)

我喜欢这个循环是:

  • 这是写作的简短
  • 无需访问(更不用说缓存)length属性
  • 要访问的项目将在您选择的名称下的循环体内自动定义.
  • 与array.push和array.splice非常自然地结合使用像列表/堆栈这样的数组

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

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

for (String item : someArray) {
}

...还有了解循环内当前索引的额外好处

  • 请注意,使用此方法,循环将在找到*falsey值*后立即停止,例如空字符串,"0","false","NaN","null"或"undefined",甚至在"i"之前到达长度,例如:http://jsfiddle.net/prvzk/1/ (13认同)
  • 循环条件可以是`(item = someArray [i])!== undefined`. (3认同)

kirilloid.. 14

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

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要使用.


molokoloco.. 14

最优雅,最快捷的方式

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>

  • -1用于修改数组,而普通循环不应该这样做.也可能影响性能测试. (14认同)
  • 打破虚假物品. (4认同)

Shubham Khat.. 14

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


Zaheer Ahmed.. 10

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

循环使用时更好更清洁:

var myStringArray = ["item1","item2"],i = myStringArray.length;
while(i--) {
   // do something with fruits[i]
}


Alongkorn Ch.. 10

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


Juanjo Salva.. 9

简短回答:是的.你可以这样做:

var myArray = ["element1", "element2", "element3", "element4"];

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

在浏览器控制台中,您可以看到打印的"element1","element2"等内容.


Espen.. 9

我认为最好的方法是使用Array.forEach函数.如果您不能使用我建议从MDN获取polyfill使我可用,它肯定是在JavaScript中迭代数组的最安全的方法.

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach

正如其他人所说,这几乎总是你想要的:

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

这可以确保您在处理数组范围内所需的任何内容都保留在该范围内,并且您只处理数组的值,而不是对象属性和其他成员,这就是.. 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/


staticd.. 8

var x = [4, 5, 6];
for (i = 0, j = x[i]; i < x.length; j = x[++i]) {
    console.log(i,j);
}

很清洁......


用户甲.. 8

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

[].forEach.call(document.getElementsByTagName('pre'), function(e){ 
   console.log(e);
})


jj_.. 8

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

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


用户甲.. 7

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

   var myStringArray = ['Hello', 'World']; // array uses [] not {}
    for (var i in myStringArray) {
        console.log(i + ' -> ' + myStringArray[i]); // i is the index/key, not the item
    }


BILAL AHMAD.. 7

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

arr = ["table", "chair"];

// solution
arr.map((e) => {
  console.log(e);
  return e;
});

  • 你宁愿使用`.forEach()`并删除`return e;` (3认同)
  • 正如`map`所暗示的那样,函数`map`用于将某个值映射到其他值,因此我不建议将这个值用于这个特定的例子. (3认同)

Daniel K... 6

当然它效率低下而且很多人鄙视它,但它是最接近上述之一的:

var myStringArray = ["Hello","World"];
myStringArray.forEach(function(f){
    // Do something
})

  • 这个确切的功能已经成为Mark Reed答案的一部分. (2认同)

Sambhav Shar.. 5

那么,这个怎么样:

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

  • 对于数组枚举,不建议使用for/in循环,因为不能保证枚举的顺序,它枚举属性,而不仅仅是数组元素.有关详细信息,请参阅http://stackoverflow.com/questions/500504/why-is-using-for-in-with-array-iteration-such-a-bad-idea,甚至是此问题的接受答案; http://stackoverflow.com/a/3010848/444991 (9认同)
  • 它仍然是气馁的,因为它枚举了所有的属性,而不仅仅是数组元素.我链接的两个帖子更详细地解释了这一点. (4认同)

Amit Jamwal.. 5

var myStringArray = ["hello", "World"];
myStringArray.forEach(function(val, index){
   console.log(val, index);
})


Andrew.. 5

看来,列出的所有变种除了forEach通过lodash:

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


提问时间:

查看次数:

3169966 次

最近活跃:

7 月,1 周 前