For-each在JavaScript中的数组?

时间:2012-02-17 13:51:49

标签: javascript arrays loops foreach iteration

如何使用JavaScript循环遍历数组中的所有条目?

我认为是这样的:

forEach(instance in theArray)

theArray是我的数组,但这似乎不正确。

37 个答案:

答案 0 :(得分:481)

修改:这个答案毫无希望地过时了。有关更现代的方法,请查看the methods available on an array。感兴趣的方法可能是:

  • 的forEach
  • 地图
  • 过滤
  • 拉链
  • 减少
  • 每个
  • 一些

JavaScript中迭代数组的标准方法是一个vanilla for循环:

var length = arr.length,
    element = null;
for (var i = 0; i < length; i++) {
  element = arr[i];
  // Do something with element
}

但请注意,只有拥有密集数组且每个索引都被一个元素占用时,此方法才有用。如果数组是稀疏的,那么你可能会遇到这种方法的性能问题,因为你将迭代很多真正存在于数组中的索引。在这种情况下,for .. in循环可能是一个更好的主意。 但是,您必须使用适当的安全措施来确保只对数组的所需属性(即数组元素)起作用,因为for..in - 循环也将被枚举在旧版浏览器中,或者如果其他属性定义为enumerable

ECMAScript 5中,阵列原型上会有一个forEach方法,但旧版浏览器不支持它。因此,为了能够始终如一地使用它,您必须具有支持它的环境(例如,服务器端JavaScript的Node.js),或使用“Polyfill”。然而,Polyfill对于这个功能来说是微不足道的,因为它使代码更容易阅读,所以它是一个很好的polyfill。

答案 1 :(得分:219)

如果您使用的是jQuery库,则可以使用jQuery.each

$.each(yourArray, function(index, value) {
  // do your stuff here
});

编辑:

根据问题,用户需要javascript中的代码而不是jquery,因此编辑是

var length = yourArray.length;   
for (var i = 0; i < length; i++) {
  // Do something with yourArray[i].
}

答案 2 :(得分:97)

向后循环

我认为 reverse for循环值得一提:

for (var i = array.length; i--; ) {
     // process array[i]
}

优点:

  • 您不需要声明临时len变量,也不需要在每次迭代时与array.length进行比较,其中任何一项都可能是一次性优化。
  • 以相反的顺序从DOM中删除兄弟姐妹通常效率更高。 (浏览器需要减少内部数组中元素的移动。)
  • 如果您在循环时修改数组,则在索引 i 之后或之后(例如,您在array[i]删除或插入项目),然后转发循环将跳过向左移动到位置 i 的项目,或者重新处理向右移动的 i 项目。在传统的for循环中,可以更新 i 以指向需要处理的下一个项目 - 1,但简单地反转迭代方向通常是更简单more elegant solution
  • 同样,在修改或删除嵌套 DOM元素时,反向处理可以规避错误。例如,在处理子节点之前,请考虑修改父节点的innerHTML。到达子节点时,它将与DOM分离,在父母的innerHTML被写入时被新创建的子节点替换。
  • 键入更短读取,比其他一些可用选项更强。虽然它会失去forEach()和ES6&#39; for ... of

缺点:

  • 以相反的顺序处理项目。如果您要从结果中构建新数组,或者在屏幕上打印内容,那么相对于原始订单,输出将会反转
  • 作为第一个孩子,为了保持秩序而反复插入兄弟姐妹效率低。 (浏览器将不得不改变方向。)要按顺序有效地创建DOM节点,只需循环前进并正常追加(并使用&#34;文档片段&#34;)。
  • 反向循环混淆给初级开发人员。 (根据您的观点,您可能会认为这是一个优势。)

我应该经常使用吗?

一些开发人员默认使用reverse for循环 ,除非有充分的理由进行循环。

虽然性能提升通常微不足道,但它有点尖叫:

  

&#34;只需对列表中的每个项目执行此操作,我都不关心订单!&#34;

然而,在实践中实际上是意图的可靠指示,因为它与 关心的情况无法区分订单,并且确实 需要 以反向循环。因此,实际上需要另一种结构来准确表达“不关心”#34; intent,大多数语言中目前不可用的东西,包括ECMAScript,但可以调用,例如,forEachUnordered()

如果订单无关紧要,并且效率是一个问题(在游戏或动画引擎的最内层循环中),则可以接受使用反向循环作为您的进入模式。请记住,在现有代码中看到反向循环并不一定意味着订单无关紧要!

最好使用forEach()

一般情况下,对于更高级别的代码,清晰度和安全性是更受关注的问题,我建议您使用Array::forEach作为默认模式:

  • 很清楚阅读。
  • 表示 i 不会在块中移位(在长forwhile循环中总是可能出现意外隐藏。)
  • 它为您提供了一个免费的闭包范围。
  • 它减少了局部变量的泄漏以及外部变量的意外碰撞(和突变)。

然后,当您在代码中看到反向循环时,这是一个暗示它被推翻的原因很充分(可能是上述原因之一)。并且看到传统的前向循环可能表明可能发生转移。

(如果对意图的讨论对你没有意义,那么你和你的代码可能会受益于观看Crockford关于Programming Style & Your Brain的讲座。)


它是如何工作的?

for (var i = 0; i < array.length; i++) { ... }   // Forwards

for (var i = array.length; i--; )    { ... }   // Reverse

您会注意到i--是中间子句(我们通常会看到比较),最后一个子句是空的(我们通常会看到i++)。这意味着i--也可用作条件来继续。至关重要的是,它会在每次迭代之前执行并检查

  • 如何在没有爆炸的情况下从array.length开始?

    因为i--每次迭代之前运行,所以在第一次迭代中我们实际上将访问array.length - 1处的项目,这避免了 Array-out-的任何问题of-bounds undefined项。

  • 为什么它不会在索引0之前停止迭代?

    当条件i--求值为假值(当它产生0时)时,循环将停止迭代。

    诀窍在于,与--i不同,尾随i--运算符会递减i,但会在 递减之前产生值 。您的控制台可以证明这一点:

    > var i = 5; [i, i--, i];

    [5, 5, 4]

    所以在最后一次迭代中, i 以前是 1 i--表达式将其更改为 0 但实际上产生<强> 1 (真实),所以条件通过。在下一次迭代i-- i 更改为 -1 但产生 0 (falsey),导致执行立即退出循环的底部。

    在循环的传统前锋中,i++++i是可以互换的(正如Douglas Crockford指出的那样)。但是在反向for循环中,因为我们的减量也是我们的条件表达式,如果我们想在索引0处理项目,我们必须坚持使用i--


琐事

有些人喜欢在反向for循环中画一个小箭头,并以眨眼结束:

for (var i = array.length; i --> 0 ;) {

积分转到WYL,向我展示反向循环的好处和恐怖。

答案 3 :(得分:76)

某些C样式语言使用foreach循环枚举。在JavaScript中,这是使用for..in loop structure

完成的
var index,
    value;
for (index in obj) {
    value = obj[index];
}

有一个问题。 for..in将循环遍历每个对象的可枚举成员以及其原型上的成员。要避免读取通过对象原型继承的值,只需检查属性是否属于对象:

for (i in obj) {
    if (obj.hasOwnProperty(i)) {
        //do stuff
    }
}

此外,ECMAScript 5已向Array.prototype添加forEach方法,该方法可用于使用calback枚举数组(polyfill位于文档中,因此您仍然可以使用它对于旧浏览器):

arr.forEach(function (val, index, theArray) {
    //do stuff
});

重要的是要注意,当回调返回Array.prototype.forEach时,false不会中断。 jQueryUnderscore.jseach上提供了自己的变体,以提供可以短路的循环。

答案 4 :(得分:36)

如果要循环数组,请使用标准的由三部分组成的for循环。

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

您可以通过缓存myArray.length或向后迭代来获得性能优化。

答案 5 :(得分:29)

我知道这是一篇很老的帖子,而且已经有很多很棒的答案了。为了更完整一点,我想我会使用AngularJS投入另一个。当然,这只适用于你使用Angular的情况,显然,无论如何我还是想把它放进去。

angular.forEach需要2个参数和一个可选的第三个参数。第一个参数是迭代的对象(数组),第二个参数是迭代器函数,可选的第三个参数是对象上下文(在循环内部基本上称为'this'。

使用forEach循环的角度有不同的方法。最简单且可能最常用的是

var temp = [1, 2, 3];
angular.forEach(temp, function(item) {
    //item will be each element in the array
    //do something
});

另一种将项目从一个数组复制到另一个数组的方法是

var temp = [1, 2, 3];
var temp2 = [];
angular.forEach(temp, function(item) {
    this.push(item); //"this" refers to the array passed into the optional third parameter so, in this case, temp2.
}, temp2);

虽然,您不必这样做,但您可以简单地执行以下操作,它与上一个示例相同:

angular.forEach(temp, function(item) {
    temp2.push(item);
});

现在有使用angular.forEach函数的优点和缺点,而不是内置的vanilla-flavored for循环。

<强>赞成

  • 易读性
  • 易于写入
  • 如果可用,angular.forEach将使用ES5 forEach循环。现在,我将在cons部分中获得效率,因为forEach循环比for循环慢。我作为专业人士提到这一点,因为保持一致和标准化是件好事。

考虑以下2个嵌套循环,这些循环完全相同。假设我们有2个对象数组,每个对象包含一个结果数组,每个结果都有一个Value属性,它是一个字符串(或其他)。并且假设我们需要迭代每个结果,如果它们相等则执行一些操作:

angular.forEach(obj1.results, function(result1) {
    angular.forEach(obj2.results, function(result2) {
        if (result1.Value === result2.Value) {
            //do something
        }
    });
});

//exact same with a for loop
for (var i = 0; i < obj1.results.length; i++) {
    for (var j = 0; j < obj2.results.length; j++) {
        if (obj1.results[i].Value === obj2.results[j].Value) {
            //do something
        }
    }
}

虽然这是一个非常简单的假设示例,但是我使用第二种方法编写了三次嵌入for循环,并且非常难以阅读,并为此写了。

<强>缺点

  • 效率。 angular.forEach和本地forEach就此而言,比正常的for循环慢得多......关于90% slower 。因此,对于大型数据集,最好坚持原生for循环。
  • 没有休息,继续或返回支持。 “accident”实际上支持continue,要继续angular.forEach,您可以在return;函数中简单地添加angular.forEach(array, function(item) { if (someConditionIsTrue) return; });语句,这将使其成为forEach继续执行该迭代的功能。这也是由于本机for不支持中断或继续。

我确信还有其他各种优点和缺点,请随意添加您认为合适的任何内容。我觉得,如果你需要效率的话,最重要的是,坚持使用本地angular.forEach循环来满足你的循环需求。但是,如果你的数据集较小并且可以放弃一些效率以换取可读性和可写性,那么无论如何都要在这个坏孩子中抛出{{1}}。

答案 6 :(得分:28)

forEach 实施(see in jsFiddle):

function forEach(list,callback) {
  var length = list.length;
  for (var n = 0; n < length; n++) {
    callback.call(list[n]);
  }
}

var myArray = ['hello','world'];

forEach(
  myArray,
  function(){
    alert(this); // do something
  }
);

答案 7 :(得分:25)

现在一个简单的解决方案是使用underscore.js library。它提供了许多有用的工具,例如each,如果可用,它会自动将作业委派给本地forEach

A CodePen example它的工作原理是:

var arr = ["elemA", "elemB", "elemC"];
_.each(arr, function(elem, index, ar)
{
...
});

另见

答案 8 :(得分:25)

jQueryforeach有三种实现方式如下。

var a = [3,2];

$(a).each(function(){console.log(this.valueOf())}); //Method 1
$.each(a, function(){console.log(this.valueOf())}); //Method 2
$.each($(a), function(){console.log(this.valueOf())}); //Method 3

答案 9 :(得分:23)

自ES6开始:

list = [0, 1, 2, 3]
for (let obj of list) {
    console.log(obj)
}

of避免与in相关联的奇怪现象,并使其像任何其他语言的for循环一样工作,let绑定i循环而不是函数。

当只有一个命令时(例如在上面的示例中),可以省略大括号({})。

答案 10 :(得分:23)

for(i = 0; i < array.length; i++)循环可能不是最好的选择。为什么?如果你有这个:

var array = new Array();
array[1] = "Hello";
array[7] = "World";
array[11] = "!";

该方法将从array[0]致电array[2]。首先,这将首先引用你甚至没有的变量,第二个你不会在数组中有变量,第三个会使代码更大胆。看这里,这就是我使用的:

for(var i in array){
    var el = array[i];
    //If you want 'i' to be INT just put parseInt(i)
    //Do something with el
}

如果你想让它成为一个功能,你可以这样做:

function foreach(array, call){
    for(var i in array){
        call(array[i]);
    }
}

如果你想打破一点逻辑:

function foreach(array, call){
    for(var i in array){
        if(call(array[i]) == false){
            break;
        }
    }
}

示例:

foreach(array, function(el){
    if(el != "!"){
        console.log(el);
    } else {
        console.log(el+"!!");
    }
});

它返回:

//Hello
//World
//!!!

答案 11 :(得分:17)

这是非稀疏列表的迭代器,其中索引从0开始,这是处理document.getElementsByTagName或document.querySelectorAll时的典型场景。

function each( fn, data ) {

    if(typeof fn == 'string')
        eval('fn = function(data, i){' + fn + '}');

    for(var i=0, L=this.length; i < L; i++) 
        fn.call( this[i], data, i );   

    return this;
}

Array.prototype.each = each;  

用法示例:

示例#1

var arr = [];
[1, 2, 3].each( function(a){ a.push( this * this}, arr);
arr = [1, 4, 9]

示例#2

each.call(document.getElementsByTagName('p'), "this.className = data;",'blue');

每个p标记获得class="blue"

示例#3

each.call(document.getElementsByTagName('p'), 
    "if( i % 2 == 0) this.className = data;",
    'red'
);

其他每个p标记都会获得class="red"&gt;

示例#4

each.call(document.querySelectorAll('p.blue'), 
    function(newClass, i) {
        if( i < 20 )
            this.className = newClass;
    }, 'green'
);

最后,前20个蓝色p标签变为绿色

使用字符串作为函数时的注意事项:该函数是在上下文中创建的,只有在您确定变量作用域时才应该使用。否则,最好传递范围更直观的函数。

答案 12 :(得分:17)

原生JavaScript中没有for each个循环。您可以使用库来获得此功能(我建议Underscore.js),在循环中使用简单的for

for (var instance in objects) {
   ...
}

但请注意,可能有理由使用更简单的for循环(请参阅堆栈溢出问题 Why is using “for…in” with array iteration such a bad idea?

var instance;
for (var i=0; i < objects.length; i++) {
    var instance = objects[i];
    ...
}

答案 13 :(得分:16)

在JavaScript中循环数组有一些方法,如下所示:

- 这是最常见的一个。用于循环的完整代码块

var languages = ["JAVA", "JavaScript", "C#", "Python"];
var i, len, text;
for (i = 0, len = languages.length, text = ""; i < len; i++) {
    text += languages[i] + "<br>";
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

while - 在条件通过时循环播放。它似乎是最快的循环

var text = "";
var i = 0;
while (i < 10) {
    text +=  i + ") something<br>";
    i++;
}
document.getElementById("example").innerHTML = text;
<p id="example"></p>

执行/同时 - 在条件为真时循环执行代码块,至少运行一次

var text = ""
var i = 0;
do {
    text += i + ") something <br>";
    i++;
}
while (i < 10);
document.getElementById("example").innerHTML = text;
<p id="example"></p>

功能循环 - forEachmapfilter,还有reduce(它们遍历函数,但如果您需要,则使用用你的阵列等做点什么。

// For example, in this case we loop through the number and double them up using the map function
var numbers = [65, 44, 12, 4];
document.getElementById("example").innerHTML = numbers.map(function(num){return num * 2});
<p id="example"></p>

有关数组上函数式编程的更多信息和示例,请查看博客文章 Functional programming in JavaScript: map, filter and reduce

答案 14 :(得分:14)

forEach没有内置的能力。要中断执行,请使用下面的Array#some

[1,2,3].some(function(number) {
    return number === 1;
});

这是有效的,因为只要以数组顺序执行的任何回调返回true,some都会返回true,从而使其余的执行短路。 Original Answer 请参阅some

的数组原型

答案 15 :(得分:14)

ECMAScript5(Javascript上的版本)与Arrays一起使用。

forEach - 遍历数组中的每个项目,并为每个项目执行任何操作。

['C', 'D', 'E'].forEach(function(element, index) {
  console.log(element + " is the #" + (index+1) + " in musical scale");
});

// Output
// C is the #1 in musical scale
// D is the #2 in musical scale
// E is the #3 in musical scale

如果使用某些内置功能对阵列操作更感兴趣。

map - 它使用回调函数的结果创建一个新数组。当您需要格式化数组元素时,可以使用此方法。

// Let's upper case the items in the array
['bob', 'joe', 'jen'].map(function(elem) {
  return elem.toUpperCase();
});

// Output: ['BOB', 'JOE', 'JEN']

reduce - 正如名称所说,它通过调用传入currenct元素的给定函数和先前执行的结果将数组减少为单个值。

[1,2,3,4].reduce(function(previous, current) {
  return previous + current;
});
// Output: 10
// 1st iteration: previous=1, current=2 => result=3
// 2nd iteration: previous=3, current=3 => result=6
// 3rd iteration: previous=6, current=4 => result=10

每个 - 如果数组中的所有元素都在回调函数中传递测试,则返回true或false。

// Check if everybody has 18 years old of more.
var ages = [30, 43, 18, 5];  
ages.every(function(elem) {  
  return elem >= 18;
});

// Output: false

过滤器 - 非常类似于除过滤器之外的每个过滤器返回一个数组,其中的元素返回true给定的函数。

// Finding the even numbers
[1,2,3,4,5,6].filter(function(elem){
  return (elem % 2 == 0)
});

// Output: [2,4,6]

希望这会有用。

答案 16 :(得分:11)

我也希望将此作为反向循环的组合添加到上面,并为那些想要这种语法的人添加答案。

var foo = [object,object,object];
for (var i = foo.length, item; item = foo[--i];) {
    console.log(item);
}

<强>优点:

这样做的好处:你已经在第一个中有了引用,就像以后不需要用另一行声明一样。循环通过对象数组时很方便。

<强>缺点:

只要引用为false,这将会中断 - falsey(未定义等)。它可以作为一个优势使用。但是,它会让它更难阅读。此外,根据浏览器的不同,它可以“优化”,以便比原始浏览器更快地工作。

答案 17 :(得分:10)

使用$.map的jQuery方式:

var data = [1, 2, 3, 4, 5, 6, 7];

var newData = $.map(data, function(element) {
    if (element % 2 == 0) {
        return element;
    }
});

// newData = [2, 4, 6];

答案 18 :(得分:7)

在ES6 destructuringspread operator中使用循环

事实证明,解构和使用散布运算符对于ES6的新手来说非常有用,因为它更易于阅读/美观,尽管有些javascript老手可能认为它比较杂乱,初级或其他人可能会觉得有用。

  

以下示例将使用for...of语句和.forEach方法。

     

示例6、7和8 可以与.map.filter.reduce.sort,{{ 1}},.every,有关这些方法的更多信息,请查看Array Object

示例1:正常的.some循环-这里没有技巧。

for...of

示例2:将单词拆分为字符

let arrSimple = ['a', 'b', 'c'];

for (let letter of arrSimple) {
  console.log(letter);
}

示例3:使用let arrFruits = ['apple', 'orange', 'banana']; for (let [firstLetter, ...restOfTheWord] of arrFruits) { // Create a shallow copy using the spread operator let [lastLetter] = [...restOfTheWord].reverse(); console.log(firstLetter, lastLetter, restOfTheWord); }key循环

value

示例4:内联获取对象属性

// let arrSimple = ['a', 'b', 'c'];

// Instead of keeping an index in `i` as per example `for(let i = 0 ; i<arrSimple.length;i++)`
// this example will use a multi-dimensional array of the following format type: 
// `arrWithIndex: [number, string][]`

let arrWithIndex = [
  [0, 'a'],
  [1, 'b'],
  [2, 'c'],
];

// Same thing can be achieved using `.map` method
// let arrWithIndex = arrSimple.map((i, idx) => [idx, i]);

// Same thing can be achieved using `Object.entries`
// NOTE: `Object.entries` method doesn't work on internet explorer unless it's polyfilled
// let arrWithIndex = Object.entries(arrSimple);

for (let [key, value] of arrWithIndex) {
  console.log(key, value);
}

示例5:获得所需的深层对象属性

let arrWithObjects = [{
    name: 'Jon',
    age: 32
  },
  {
    name: 'Elise',
    age: 33
  }
];

for (let { name, age: aliasForAge } of arrWithObjects) {
  console.log(name, aliasForAge);
}

示例6:示例3 let arrWithObjectsWithArr = [{ name: 'Jon', age: 32, tags: ['driver', 'chef', 'jogger'] }, { name: 'Elise', age: 33, tags: ['best chef', 'singer', 'dancer'] } ]; for (let { name, tags: [firstItemFromTags, ...restOfTags] } of arrWithObjectsWithArr) { console.log(name, firstItemFromTags, restOfTags); }

一起使用

.forEach

示例7:是否与let arrWithIndex = [ [0, 'a'], [1, 'b'], [2, 'c'], ]; // Not to be confused here, `forEachIndex` is the real index // `mappedIndex` was created by "another user", so you can't really trust it arrWithIndex.forEach(([mappedIndex, item], forEachIndex) => { console.log(forEachIndex, mappedIndex, item); });

一起使用示例4

.forEach

示例8:示例5 let arrWithObjects = [{ name: 'Jon', age: 32 }, { name: 'Elise', age: 33 } ]; // NOTE: Destructuring objects while using shorthand functions // are required to be surrounded by parenthesis arrWithObjects.forEach( ({ name, age: aliasForAge }) => { console.log(name, aliasForAge) });

一起使用

.forEach

答案 19 :(得分:6)

最接近你想法的方法是使用Array.forEach()接受将为数组的每个元素执行的clojure函数。

myArray.forEach(
  (item) => {
    // do something 
    console.log(item);
  }
);

另一种可行的方法是使用Array.map(),它以相同的方式工作,但每个元素也mutates,并返回它:

var myArray = [1, 2, 3];
myArray = myArray.map(
  (item) => {
    return item + 1;
  }
);

console.log(myArray); // [2, 3, 4]

答案 20 :(得分:5)

根据新的更新功能ECMAScript 6(ES6)和ECMAScript 2015,您可以在循环中使用以下选项:

用于循环

for(var i = 0; i < 5; i++){
  console.log(i);
}

// Output: 0,1,2,3,4

用于...循环

let obj = {"a":1, "b":2}

for(let k in obj){
  console.log(k)
}

// Output: a,b

Array.forEach()

let array = [1,2,3,4]

array.forEach((x) => {
  console.log(x);
})

// Output: 1,2,3,4

用于...的循环

let array = [1,2,3,4]

for(let x of array){
  console.log(x);
}

// Output: 1,2,3,4

while循环

let x = 0

while(x < 5){
  console.log(x)
  x++
}

// Output: 1,2,3,4

做...而循环

let x = 0

do{
  console.log(x)
  x++
}while(x < 5)

// Output: 1,2,3,4

答案 21 :(得分:5)

lambda语法通常不适用于IE 10或更低版本。

我通常使用

converters

答案 22 :(得分:4)

您可以像这样致电forEach

let Array = [1,3,2];

theArray.forEach((element)=>{ 
  // use the element of the array
  console.log(element) 
}

element具有从0到数组长度的每个索引的值。

输出:

1    
3    
2

说明:

forEach在原型类中。您也可以将其称为theArray.prototype.forEach(...);

原型: https://hackernoon.com/prototypes-in-javascript-5bba2990e04b

您还可以像这样更改数组:

for(let i=0;i<theArray.length;i++){
  console.log(i); //i will have the value of each index
}

答案 23 :(得分:4)

您可以使用: 1. ForEach

theArray.forEach(function (array, index) {
    console.log(index);
    console.log(array);
});

2.for

for(var i=0;i<theArray.length;i++){
console.log(i)
}

3.map

theArray.map(x => console.log(x));

4.map

theArray.filter(x => console.log(x));

还有很多其他需要迭代的地方

答案 24 :(得分:3)

假设我们有一系列主题:

  let ddl = new Array();
    if (subjects) {
      subjects.forEach(function (s) {ddl.push({"id": s.id,"label": s.name});});
    }

答案 25 :(得分:3)

如果要使用箭头功能遍历对象数组:

let arr=[{name:'john',age:50},{name:'clark',age:19},{name:'mohan',age:26}];

arr.forEach((person)=>{
  console.log('i am '+person.name+' and i am '+person.age+ ' old');
})

答案 26 :(得分:2)

摘要:

遍历数组时,我们通常可能希望实现以下目标之一:

  1. 我们要遍历数组并创建新数组:

    Array.prototype.map

  2. 我们要遍历数组,而不要创建新的数组:

    Array.prototype.forEach

    for..of 循环

在JS中,有许多方法可以实现这两个目标。但是,有些比其他更方便。在下面,您可以找到一些常用的方法(最方便的imo)来完成javascript中的数组迭代。

创建新数组:Map

map()是位于Array.prototype上的函数,可以转换数组的每个元素,然后返回一个 new 数组。 map()以回调函数作为参数,并以下列方式工作:

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

let newArr = arr.map((element, index, array) => {
  return element * 2;
})

console.log(arr);
console.log(newArr);

我们已传递给map()作为参数的回调函数,将对每个元素执行。然后返回一个数组,该数组的长度与原始数组的长度相同。在这个新数组元素中,回调函数将其作为参数传递给map()

map与其他循环机制(如forEachfor..of循环)之间的明显区别在于, map返回为新数组,而旧数组完好无损(除非您明确使用splice之类的方式进行操作)。

还要注意,map函数的回调提供了当前迭代的索引号作为第二个参数。此外,第三个参数是否提供了在其上调用map的数组。有时,这些属性可能非常有用。

使用forEach

forEach是位于Array.prototype上的函数,该函数以回调函数作为参数。然后,它将对数组中的每个元素执行此回调函数。与map()函数相反,forEach函数不返回任何内容(undefined)。例如:

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

arr.forEach((element, index, array) => {

  console.log(element * 2);

  if (index === 4) {
    console.log(array)
  }
  // index, and oldArray are provided as 2nd and 3th argument by the callback

})

console.log(arr);

就像map函数一样,forEach回调提供第二个参数作为当前迭代的索引号。第三个参数也提供在其上调用forEach的数组。

使用for..of

遍历元素

for..of循环遍历数组的每个元素(或任何其他可迭代对象)。它以以下方式工作:

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

for(let element of arr) {
  console.log(element * 2);
}

在上面的示例中,element代表数组元素,arr是我们要循环的数组。并不是说element是一个任意名称,我们可以选择其他任何名称,例如'el'或适用时更具声明性的名称。

不要将for..in循环与for..of循环混淆。 for..in将循环遍历数组的所有可枚举属性,而for..of循环将仅遍历数组元素。例如:

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

arr.foo = 'foo';

for(let element of arr) {
  console.log(element);
}

for(let element in arr) {
  console.log(element);
}

答案 27 :(得分:1)

如果您想使代码保持功能性,请使用map:

theArray.map(instance => do_something);

通过这种方式,您将为以后的操作生成新的数组,并将跳过任何不希望的副作用。

答案 28 :(得分:1)

性能

今天18/12/2019,我在MacOs HighSierra 10.13.6,Chrome v 79.0,Safari v13.0.4和Firefox v71.0(64位)上进行了测试-有关优化的结论(通常micro-optimisation不值得将其引入代码中,因为收益很小,但是代码复杂度却不断提高。

  • 看起来像传统的for Aa )是在所有浏览器上编写快速代码的不错选择。

  • C组中的其他解决方案,例如for-of Ad )。 ...通常是2x-10x(甚至更多)速度比 Aa 慢1倍,但是对于较小的数组,可以使用它-为了提高代码的清晰度。

  • n Ab,Bb,Be )中缓存有数组长度的循环有时更快,有时却没有。可能是编译器自动检测这种情况并引入缓存。缓存版本和非缓存版本( Aa,Ba,Bd )之间的速度差异约为1%-因此,简介nmicro-optimisation

  • 类似i--的解决方案,其中循环从最后一个数组元素( Ac,Bc )开始,通常比向前解决方案慢30%-可能是这样的的CPU memory cache working中的值-前向内存读取对于CPU缓存而言更为理想。 建议不要使用此类解决方案。

详细信息

在测试中,我们计算数组元素的总和。我对小型数组(10个元素)和大型数组(1M元素)进行测试,并将它们分为3组:

  • A -for个测试
  • B -while测试
  • C -其他/替代方法

let arr=[1,2,3,4,5,6,7,8,9,10];
//let arr = Array.from(Array(1000000), (x,i)=> i%10);

function Aa(a,s=0) { 
  for(let i=0; i<a.length; i++) { s+= a[i]; } 
  console.log('Aa=',s);
}

function Ab(a,s=0) { 
  let n= a.length;
  for(let i=0; i<n; i++) { s+= a[i]; } 
  console.log('Ab=',s);
}

function Ac(a,s=0) { 
  for(let i=a.length; i--;) { s+= a[i]; } 
  console.log('Ac=',s);
}

function Ad(a,s=0) {
  for(let x of a) { s+=x; }
  console.log('Ad=',s);
}

function Ae(a,s=0) {
  for(let i in a) if (a.hasOwnProperty(i)) { s+=a[i]; }
  console.log('Ae=',s);
}

function Ba(a,s=0) {
  let i= -1;
  while(++i < a.length) { s+= a[i]; }
  console.log('Ba=',s);  
}

function Bb(a,s=0) {
  let i= -1; let n= a.length;
  while(++i < n) { s+= a[i]; }
  console.log('Bb=',s);  
}

function Bc(a,s=0) {
  let i=a.length;
  while(i--) { s+= a[i]; }
  console.log('Bc=',s);  
}

function Bd(a,s=0) {
  let i=0;
  do { s+= a[i] } while (++i < a.length);
  console.log('Bd=',s);  
}

function Be(a,s=0) {
  let i=0; let n=a.length;
  do { s+= a[i] } while (++i < n);
  console.log('Be=',s);  
}

function Bf(a,s=0) {
  const it = a.values(); let e;
  while (!(e = it.next()).done) { s+= e.value; }  
  console.log('Bf=',s);  
}

function Ca(a,s=0) {
  a.map(x => { s+=x });
  console.log('Ca=',s);  
}

function Cb(a,s=0) {
  a.forEach(x => { s+=x });
  console.log('Cb=',s);  
}

function Cc(a,s=0) {
  a.every(x => (s+=x,1) );
  console.log('Cc=',s);  
}

function Cd(a,s=0) {
  a.filter(x => { s+=x } );
  console.log('Cd=',s);  
}

function Ce(a,s=0) {
  a.reduce( (z,c) => { s+=c }, 0 );
  console.log('Ce=',s);  
}

function Cf(a,s=0) {
  a.reduceRight( (z,c) => { s+=c }, 0 );
  console.log('Cf=',s);  
}

function Cg(a,s=0) {
  a.some(x => { s+=x } );
  console.log('Cg=',s);  
}

function Ch(a,s=0) {
  Array.from(a, x=> s+=x);
  console.log('Cc=',s);  
}


Aa(arr);
Ab(arr);
Ac(arr);
Ad(arr);
Ae(arr);

Ba(arr);
Bb(arr);
Bc(arr);
Bd(arr);
Be(arr);
Bf(arr);

Ca(arr);
Cb(arr);
Cc(arr);
Cd(arr);
Ce(arr);
Cf(arr);
Cg(arr);
Ch(arr);
<p style="color: red">This snippets only PRESENTS code used for benchmark - it not perform test itself</p>

跨浏览器结果

所有经过测试的浏览器的结果

enter image description here浏览器**

包含10个元素的数组

Chrome的搜索结果。您可以在计算机here

上执行测试

enter image description here

包含1.000.000个元素的数组

Chrome的搜索结果。您可以在计算机here

上执行测试

enter image description here

答案 29 :(得分:1)

var a = ["car", "bus", "truck"]
a.forEach(function(item, index) {
    console.log("Index" + index);
    console.log("Element" + item);
})

答案 30 :(得分:1)

// Looping through arrays using foreach  ES6 way

var data = new Array(1,2,3,4,5);
data.forEach((val,index) => {
    console.log("index :",index); // index
	console.log("value :", val); // value
});

答案 31 :(得分:1)

如果阵列数量庞大,则应使用iterators来提高效率。迭代器是某些JavaScript集合(例如MapSetStringArray)的属性。甚至for..of都使用 iterator

迭代器可让您一次使用列表中的项目,就好像它们是流一样,从而提高了效率。使迭代器与众不同的是它如何遍历集合。其他循环需要预先加载整个集合以便对其进行迭代,而迭代器仅需要知道集合中的当前位置。

您可以通过调用迭代器的next方法来访问当前项目。下一个方法将返回当前项目的 value 和一个 boolean ,以指示您何时到达集合的末尾。以下是从数组创建迭代器的示例。

使用values()这样的方法将常规数组转换为迭代器:

    const myArr = [2,3,4]

let it = myArr.values();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您还可以使用Symbol.iterator将常规数组转换为迭代器,如下所示:

const myArr = [2,3,4]

let it = myArr[Symbol.iterator]();

console.log(it.next());
console.log(it.next());
console.log(it.next());
console.log(it.next());

您还可以将常规array转换为iterator,如下所示:

let myArr = [8, 10, 12];

function makeIterator(array) {
    var nextIndex = 0;
    
    return {
       next: function() {
           return nextIndex < array.length ?
               {value: array[nextIndex++], done: false} :
               {done: true};
       }
    };
};

var it = makeIterator(myArr);

console.log(it.next().value);   // {value: 8, done: false}
console.log(it.next().value);   // {value: 10, done: false}
console.log(it.next().value);   // {value: 12, done: false}
console.log(it.next().value);   // {value: undefined, done: true}

注意

  • 迭代器本质上是穷举的。
  • 默认情况下,对象不是iterable。在这种情况下,请使用for..in,因为它可以使用键代替值。

您可以阅读有关iteration protocol here的更多信息。

答案 32 :(得分:0)

Mozilla Docs

/* get all form */
document.querySelectorAll( "form" ).forEach( form => {
  
  /* each form add onsubmit event */
  form.addEventListener( "submit", event => {
    event.preventDefault(); // return false

    /* display it */
    alert(event.target.action);
    console.log(event.target);    
  } );

} );
<form action="form1.php" >
  <input type="submit" value="Submit" />
</form>
<form action="form2.php" >
  <input type="submit" value="Submit" />
</form>
<form action="form3.php" >
  <input type="submit" value="Submit" />
</form>

答案 33 :(得分:0)

我来自python,发现这种方法更加清晰。
theArray是数组,实例是数组的元素

for(let instance of theArray)
{
    console.log("The instance",instance);
}

for( instance in theArray)
{
  console.log("The instance",instance);
}

比较:

theArray.forEach(function(instance) {
    console.log(instance);
});

但是到了最后,他们俩都在做同一件事

答案 34 :(得分:0)

我认为for/of是必经之路:

const arr = ['a', 'b', 'c'];

for (const v of arr) {
  console.log(v); // Prints "a", "b", "c"
}
  • for/in不同,for/of会跳过数组上的非数字属性。例如,如果您设置了arr.foo = 'test',则for (var v in arr)将通过'foo'键进行循环。

  • forEach()不同,for/of不会跳过数组中的“空洞”。 const arr = ['a',, 'c']是有效的JavaScript,仅第二个元素是“ hole”。该数组在功能上等效于['a', undefined, 'c']

您可以在this blog post on for/of vs forEach().

中阅读更多内容

答案 35 :(得分:0)

如果您想使用forEach(),它会看起来像 -

theArray.forEach ( element => {
    console.log(element);
});

如果您想使用for(),它会看起来像 -

for(let idx = 0; idx < theArray.length; idx++){
    let element = theArray[idx];
    console.log(element);
}

答案 36 :(得分:-1)

在jQuery中使用 grep 函数,例如:

$.grep([0, 1, 2], function(n, i) {
    return n > 0;
});