在javascript中For-each 数组

For-each over an array in JavaScript?

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

我以为是这样的:

1
forEach(instance in theArray)

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


假设您想在NodechildNodes属性上使用forEach。你会这样做:好的。

1
2
3
Array.prototype.forEach.call(node.childNodes, function(child) {
    // Do something with `child`
});

如果要经常这样做,可能需要将函数引用的副本抓取到变量中以便重用,例如:好的。

1
2
3
4
5
6
7
// (This is all presumably in some scoping function)
var forEach = Array.prototype.forEach;

// Then later...
forEach.call(node.childNodes, function(child) {
    // Do something with `child`
});
  • 使用一个简单的for循环好的。

    显然,一个简单的for循环应用于类似数组的对象。好的。

  • 正确使用for-in。好的。

    与阵列具有相同安全保护的for-in也应适用于类似阵列的对象;上述1中主机提供的对象的警告可能适用。好的。

  • 使用for-of(隐式使用迭代器)(es2015+)好的。

    for-of将使用对象提供的迭代器(如果有的话);我们将不得不了解它如何处理各种类似数组的对象,特别是主机提供的对象。例如,来自querySelectorAllNodeList的规范被更新以支持迭代。来自getElementsByTagNameHTMLCollection的规格不是。好的。

  • 显式使用迭代器(ES2015+)好的。

    看4,我们要看看迭代器是如何发挥作用的。好的。

  • 创建真数组

    有时,您可能希望将类似数组的对象转换为真正的数组。这样做非常容易:好的。

  • 使用数组的slice方法好的。

    我们可以使用数组的slice方法,与上面提到的其他方法一样,这些方法是"有意通用的",因此可以用于类似数组的对象,如:好的。

    1
    var trueArray = Array.prototype.slice.call(arrayLikeObject);

    例如,如果我们想将一个NodeList转换成一个真正的数组,我们可以这样做:好的。

    1
    var divs = Array.prototype.slice.call(document.querySelectorAll("div"));

    请参见下面主机提供的对象的警告。特别要注意,在IE8和更早版本中,这将失败,因为它不允许您将宿主提供的对象用作这样的this。好的。

  • 使用排列语法(...)好的。

    还可以在支持此功能的JavaScript引擎中使用ES2015的Spread语法:好的。

    1
    var trueArray = [...iterableObject];

    例如,如果我们想将NodeList转换成一个真正的数组,使用spread语法,这会变得非常简洁:好的。

    1
    var divs = [...document.querySelectorAll("div")];
  • 使用Array.from(规格)(MDN)好的。

    Array.from(es2015+,但很容易被多填充)从类似数组的对象创建一个数组,可以选择先通过映射函数传递条目。所以:好的。

    1
    var divs = Array.from(document.querySelectorAll("div"));

    或者,如果要获取具有给定类的元素的标记名数组,可以使用mapping函数:好的。

    1
    2
    3
    4
    5
    6
    7
    // Arrow function (ES2015):
    var divs = Array.from(document.querySelectorAll(".some-class"), element => element.tagName);

    // Standard function (since `Array.from` can be shimmed):
    var divs = Array.from(document.querySelectorAll(".some-class"), function(element) {
        return element.tagName;
    });
  • 主机提供对象的警告

    如果将Array.prototype函数与主机提供的类似数组的对象(dom列表和浏览器提供的其他内容,而不是javascript引擎)一起使用,则需要确保在目标环境中进行测试,以确保主机提供的对象的行为正常。大多数人(现在)行为正常,但测试很重要。原因是,大多数您可能希望使用的Array.prototype方法依赖于宿主提供的对象,对抽象[[HasProperty]]操作给出了诚实的答案。在本文中,浏览器做得很好,但是5.1规范允许主机提供的对象可能不诚实。在第8.6.2节中,大桌子下面靠近该节开头的几段),上面写着:好的。

    Host objects may implement these internal methods in any manner unless specified otherwise; for example, one possibility is that [[Get]] and [[Put]] for a particular host object indeed fetch and store property values but [[HasProperty]] always generates false.

    Ok.

    (我在ES2015规范中找不到相同的措辞,但肯定仍然如此。)同样,在撰写本文时,公共主机在现代浏览器中提供了类似数组的对象[例如,NodeList个实例]确实正确地处理[[HasProperty]],但测试很重要。)好的。好啊。

    DR好的。

    • 不要使用for-in,除非你使用它时有安全措施或者至少知道它为什么会咬你。
    • 你最好的赌注通常是好的。

      • 一个for-of环路(仅限ES2015+
      • Array#forEach(specMDN(或其亲属some等)(仅限es5+)
      • 一个简单的老式的for循环,
      • 或有防护措施的for-in

    但是还有很多东西需要探索,继续阅读…好的。

    javascript具有强大的语义,可以循环遍历数组和类似数组的对象。我将答案分为两部分:用于真正数组的选项,以及用于类似于数组的对象的选项,例如arguments对象、其他无法识别的对象(es2015+)、dom集合等。好的。

    我会很快注意到,通过将ES2015扩展到ES5,您现在可以使用ES2015选项,甚至在ES5引擎上也是如此。搜索"ES2015蒸腾"/"ES6蒸腾"了解更多…好的。

    好吧,让我们看看我们的选择:好的。对于实际数组

    EcmaScript 5("ES5")中有三个选项,是目前最广泛支持的版本,在EcmaScript 2015("ES2015","ES6")中又增加了两个选项:好的。

  • 使用forEach和相关(es5+)
  • 使用一个简单的for循环
  • 正确使用EDOCX1[0]
  • 使用for-of(隐式使用迭代器)(es2015+)
  • 显式使用迭代器(ES2015+)
  • 细节:好的。1。使用forEach及相关

    在任何模糊的现代环境中(因此,不是IE8),您可以使用ES5(直接或使用polyfills)添加的Array功能,您可以使用forEach(specMDN:好的。

    1
    2
    3
    4
    var a = ["a","b","c"];
    a.forEach(function(entry) {
        console.log(entry);
    });

    好的。

    forEach接受回调函数,并且可以选择在调用回调时用作this的值(上面不使用)。对数组中的每个条目依次调用回调,跳过稀疏数组中不存在的条目。尽管我在上面只使用了一个参数,但是回调是用三个参数来调用的:每个条目的值、该条目的索引,以及对要迭代的数组的引用(以防函数还没有使用它)。好的。

    除非您支持像IE8这样过时的浏览器(截至2016年9月的这篇文章中,netaps的市场份额刚刚超过4%),否则您可以在通用网页中愉快地使用forEach,而不需要填充程序。如果您确实需要支持过时的浏览器,填充/多填充forEach很容易完成(搜索"es5填充"可获得多个选项)。好的。

    forEach的好处是,您不必在包含范围内声明索引和值变量,因为它们被作为迭代函数的参数提供,并且非常适合于该迭代。好的。

    如果您担心对每个数组条目进行函数调用的运行时开销,请不要担心;详细信息。好的。

    此外,forEach是"全部循环"功能,但是es5定义了其他一些有用的"通过数组工作并做事情"功能,包括:好的。

    • every(回调第一次返回false或错误时停止循环)
    • some(在回调第一次返回true或其他真实的东西时停止循环)
    • filter(创建一个新的数组,包括过滤函数返回true的元素,省略返回false的元素)
    • map(根据回调返回的值创建一个新数组)
    • reduce(通过反复调用回调、传递以前的值来建立一个值;有关详细信息,请参阅规范;用于汇总数组内容和许多其他内容)
    • reduceRight(如reduce,但按降序而不是升序工作)

    2。使用一个简单的for循环

    有时旧方法是最好的:好的。

    1
    2
    3
    4
    5
    var index;
    var a = ["a","b","c"];
    for (index = 0; index < a.length; ++index) {
        console.log(a[index]);
    }

    好的。

    如果数组的长度在循环过程中不会改变,而且是在性能敏感的代码中(不太可能),那么在前面捕获长度的稍微复杂一点的版本可能会快一点:好的。

    1
    2
    3
    4
    5
    var index, len;
    var a = ["a","b","c"];
    for (index = 0, len = a.length; index < len; ++index) {
        console.log(a[index]);
    }

    好的。

    和/或倒数:好的。

    1
    2
    3
    4
    5
    var index;
    var a = ["a","b","c"];
    for (index = a.length - 1; index >= 0; --index) {
        console.log(a[index]);
    }

    好的。

    但是使用现代的JavaScript引擎,你很少需要补充最后一点内容。好的。

    在ES2015及更高版本中,您可以将索引和值变量设置为for循环的局部变量:好的。

    1
    2
    3
    4
    5
    6
    7
    let a = ["a","b","c"];
    for (let index = 0; index < a.length; ++index) {
        let value = a[index];
        console.log(index, value);
    }
    //console.log(index);   // would cause"ReferenceError: index is not defined"
    //console.log(value);   // would cause"ReferenceError: value is not defined"

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    let a = ["a","b","c"];
    for (let index = 0; index < a.length; ++index) {
        let value = a[index];
        console.log(index, value);
    }
    try {
        console.log(index);
    } catch (e) {
        console.error(e);   //"ReferenceError: index is not defined"
    }
    try {
        console.log(value);
    } catch (e) {
        console.error(e);   //"ReferenceError: value is not defined"
    }

    好的。

    当您这样做时,不仅为每个循环迭代重新创建value,而且也为每个循环迭代重新创建index,这意味着在循环体中创建的闭包保持对为该特定迭代创建的EDOCX1(和value)的引用:好的。

    1
    2
    3
    4
    5
    6
    let divs = document.querySelectorAll("div");
    for (let index = 0; index < divs.length; ++index) {
        divs[index].addEventListener('click', e => {
            console.log("Index is:" + index);
        });
    }

    1
    2
    3
    4
    5
    6
    let divs = document.querySelectorAll("div");
    for (let index = 0; index < divs.length; ++index) {
        divs[index].addEventListener('click', e => {
            console.log("Index is:" + index);
        });
    }
    1
    2
    3
    4
    5
    zero
    one
    two
    three
    four

    好的。

    如果你有五个div,如果你点击第一个,你会得到"index is:0",如果你点击最后一个,你会得到"index is:4"。如果您使用var而不是let,则这不起作用。好的。三。正确使用for-in

    你会得到人们告诉你使用for-in,但这不是for-in的目的。for-in循环遍历对象的可枚举属性,而不是数组的索引。即使在ES2015(ES6)中,订单也没有得到保证。ES2015+定义了一个对象属性的顺序(通过[[OwnPropertyKeys]][[Enumerate]],以及使用它们的事物,如Object.getOwnPropertyKeys,但它没有定义for-in将遵循该顺序。(其他答案中有详细信息。)好的。

    阵列上for-in的唯一实际用例是:好的。

    • 它是一个稀疏的阵列,其中有巨大的间隙,或者
    • 您正在使用非元素属性,并且希望将它们包含在循环中

    仅查看第一个示例:如果使用适当的保护措施,则可以使用for-in访问这些sparese数组元素:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    // `a` is a sparse array
    var key;
    var a = [];
    a[0] ="a";
    a[10] ="b";
    a[10000] ="c";
    for (key in a) {
        if (a.hasOwnProperty(key)  &&        // These checks are
            /^0$|^[1-9]\d*$/.test(key) &&    // explained
            key <= 4294967294                // below
            ) {
            console.log(a[key]);
        }
    }

    好的。

    注意这三项检查:好的。

  • 对象具有该名称的自身属性(不是从原型继承的属性),以及好的。

  • 该键是所有十进制数字(例如,普通字符串形式,而不是科学记数法),以及好的。

  • 当强制为数字时,键的值<=2^32-2(即4294967294)。那个号码是从哪里来的?它是规范中数组索引定义的一部分。其他数字(非整数、负数、大于2^32-2的数字)不是数组索引。之所以是2^32-2,是因为它使最大的索引值小于2^32-1,这是数组的length所能具有的最大值。(例如,数组的长度适合一个32位无符号整数。)(Robg在我的博客文章中指出,我以前的测试不太正确的一个建议。)好的。

  • 当然,在内联代码中不会这样做。你可以写一个实用函数。也许:好的。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    // Utility function for antiquated environments without `forEach`
    var hasOwn = Object.prototype.hasOwnProperty;
    var rexNum = /^0$|^[1-9]\d*$/;
    function sparseEach(array, callback, thisArg) {
        var index;
        for (var key in array) {
            index = +key;
            if (hasOwn.call(a, key) &&
                rexNum.test(key) &&
                index <= 4294967294
                ) {
                callback.call(thisArg, array[key], index, array);
            }
        }
    }

    var a = [];
    a[5] ="five";
    a[10] ="ten";
    a[100000] ="one hundred thousand";
    a.b ="bee";

    sparseEach(a, function(value, index) {
        console.log("Value at" + index +" is" + value);
    });

    好的。4。使用for-of(隐式使用迭代器)(es2015+)

    ES2015为javascript添加了迭代器。使用迭代器的最简单方法是新的for-of语句。看起来是这样的:好的。

    1
    2
    3
    4
    const a = ["a","b","c"];
    for (const val of a) {
        console.log(val);
    }

    好的。

    在封面下,它从数组中获取一个迭代器并循环遍历它,从中获取值。这并没有使用for-in的问题,因为它使用对象(数组)定义的迭代器,数组定义迭代器遍历其条目(而不是属性)。与es5中的for-in不同,条目的访问顺序是其索引的数字顺序。好的。5。显式使用迭代器(ES2015+)

    有时,您可能需要显式地使用迭代器。你也可以这样做,尽管它比for-of要笨重得多。看起来是这样的:好的。

    1
    2
    3
    4
    5
    6
    const a = ["a","b","c"];
    const it = a.values();
    let entry;
    while (!(entry = it.next()).done) {
        console.log(entry.value);
    }

    好的。

    迭代器是与规范中的迭代器定义匹配的对象。它的next方法每次调用时都返回一个新的result对象。结果对象有一个属性done,告诉我们它是否完成了,以及一个属性value,它具有该迭代的值。(如果是falsevalue是可选的;如果是undefinedvalue是可选的。)好的。

    value的含义因迭代器而异;数组支持(至少)三个返回迭代器的函数:好的。

    • 以东十一〔21〕这是我上面用过的。它返回一个迭代器,其中每个value都是该迭代的数组条目(前面例子中的"a""b""c")。
    • keys():返回一个迭代器,其中每个value是该迭代的关键(因此对于上面的a,它是"0",然后是"1",然后是"2"
    • entries():返回一个迭代器,其中每个value都是该迭代的[key, value]形式的数组。

    对于类似数组的对象

    除了真数组之外,还有类似数组的对象,它们具有length属性和具有数字名称的属性:NodeList实例、arguments对象等。我们如何循环它们的内容?好的。对数组使用上面的任何选项

    上面提到的数组方法中,至少有一部分(可能是大部分甚至全部)经常同样适用于类似数组的对象:好的。

  • 使用forEach和相关(es5+)好的。

    Array.prototype上的各种功能是"有意通用的",通常可以通过Function#callFunction#apply在类似数组的对象上使用。(请参阅本答案末尾主机提供的对象的警告,但这是一个罕见的问题。)好的。


    编辑:这个答案完全过时了。要获得更现代的方法,请查看数组上可用的方法。感兴趣的方法可能是:

    • 前额
    • 地图
    • 滤波器
    • 拉链
    • 减少
    • 每一个
    • 一些

    在javascript中迭代数组的标准方法是一个普通的for循环:

    1
    2
    3
    4
    5
    6
    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方法,但在传统浏览器中不支持它。因此,为了能够始终如一地使用它,您必须拥有支持它的环境(例如,node.js用于服务器端的javascript),或者使用"polyfill"。然而,此功能的polyfill非常简单,因为它使代码更容易阅读,所以它是一个很好的polyfill。


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

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

    编辑:

    根据问题,用户希望使用javascript而不是jquery进行代码编辑,因此

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


    向后循环

    我认为倒循环值得一提:好的。

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

    优势:

    • 您不需要声明一个临时的len变量,也不需要在每次迭代中与array.length进行比较,这两种方法都可能是一分钟的优化。
    • 以相反的顺序从DOM中删除兄弟姐妹通常更有效。(浏览器需要减少内部数组中元素的移动。)
    • 如果在循环时修改数组,在索引i处或索引i之后(例如,在array[i]处删除或插入一个项),则前循环将跳过向左移动到位置i的项,或重新处理向右移动的第i个项。在传统的for循环中,您可以更新i以指向下一个需要处理的项-1,但是简单地反转迭代的方向通常是一个更简单和更优雅的解决方案。
    • 同样,在修改或删除嵌套的DOM元素时,反向处理可以避免错误。例如,在处理父节点的子节点之前,请考虑修改父节点的innerhtml。当到达子节点时,它将从DOM中分离出来,在编写父节点的innerhtml时被新创建的子节点替换。
    • 它的输入和读取比其他一些可用选项要短。虽然输给了埃多克斯1〔3〕和埃斯6的埃多克斯1〔4〕。

    缺点:

    • 它按相反的顺序处理项目。如果您正在根据结果构建一个新的数组,或者在屏幕上打印内容,那么输出自然会与原始顺序相反。
    • 重复地将兄弟姐妹作为第一个子级插入到DOM中以保持其顺序的效率较低。(浏览器必须不断地调整方向。)为了高效有序地创建DOM节点,只需按正常方式向前循环和追加(也可以使用"文档片段")。
    • 对于初级开发人员来说,反向循环是令人困惑的。(你可能认为这是一个优势,取决于你的前景。)

    我应该一直使用它吗?

    有些开发人员默认使用反向for循环,除非有充分的理由向前循环。好的。

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

    "Just do this to every item in the list, I don't care about the order!"

    Ok.

    然而,在实践中,这实际上并不是一个意图的可靠指示,因为它与那些你关心秩序的场合是不可区分的,而且确实需要反向循环。因此,实际上,需要另一个构造来准确地表达"不在乎"的意图,这是目前大多数语言(包括ecmascript)都不可用的,但可以称为forEachUnordered()。好的。

    如果顺序无关紧要,并且效率是一个问题(在游戏或动画引擎的最里面的循环中),那么使用reverse for loop作为进入模式可能是可以接受的。请记住,在现有代码中看到循环的反转并不一定意味着顺序不相关!好的。最好使用foreach()。

    一般来说,对于更高级别的代码,如果更关注清晰度和安全性,我建议使用Array::forEach作为默认模式:好的。

    • 看书很清楚。
    • 它表明我不会在块内移动(这在长的forwhile循环中总是一个可能的惊喜)。
    • 它为闭包提供了一个自由的空间。
    • 它减少了局部变量的泄漏和与外部变量的意外碰撞(和突变)。

    然后,当您在代码中看到reverse for loop时,这是一个提示,它是出于一个很好的原因(可能是上面描述的其中一个原因)而被反转的。而看到传统的"向前-向前"循环可能表明发生了变化。好的。

    (如果对意图的讨论对您没有意义,那么您和您的代码可能会受益于观看Crockford关于编程风格和您的大脑的演讲。)好的。它是如何工作的?

    1
    2
    3
    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 boundsundefined项目有关的任何问题。好的。

    • 为什么不在索引0之前停止迭代?好的。

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

      诀窍是,与--i不同,后面的i--操作符减少i,但在减少之前生成值。您的控制台可以演示:好的。

      > var i = 5; [i, i--, i];好的。

      [5, 5, 4]好的。

      所以在最后一次迭代中,我以前是1,i--表达式将其更改为0,但实际上生成1(truthy),所以条件通过了。在下一个迭代中,i--将i更改为-1,但生成0(错误),导致执行立即从循环底部退出。好的。

      在传统的for loop中,i++++i可以互换(正如道格拉斯·克罗克福德指出的那样)。但是在相反的for循环中,由于减量也是我们的条件表达式,因此如果我们想处理索引0处的项,必须坚持使用i--。好的。

    琐事

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

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

    学分归Wyl,因为它向我展示了反向for循环的好处和恐怖之处。好的。好啊。


    一些C语言使用foreach循环枚举。在javascript中,这是通过for..in循环结构完成的:

    1
    2
    3
    4
    5
    var index,
        value;
    for (index in obj) {
        value = obj[index];
    }

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

    1
    2
    3
    4
    5
    for (i in obj) {
        if (obj.hasOwnProperty(i)) {
            //do stuff
        }
    }

    另外,ecmascript 5在Array.prototype中添加了一个foreach方法,该方法可用于使用calback枚举数组(polyfill在文档中,因此您仍可以将其用于旧浏览器):

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

    需要注意的是,当回调返回false时,Array.prototype.forEach不会中断。jquery和underline.js在each上提供自己的变体,以提供可以短路的循环。


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

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

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


    我知道这是一个古老的帖子,已经有很多好的答案了。为了更完整一点,我想我会用安古拉吉斯加上另一个。当然,这只适用于使用角的情况,显然,尽管如此,我还是想说。

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

    有不同的方法可以使用角度的前臂环。最简单和可能最常用的是

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

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

    1
    2
    3
    4
    5
    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);

    不过,您不必这样做,您只需执行以下操作,这相当于前面的示例:

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

    现在,与内置香草味的for循环相比,使用angular.forEach功能有很多优点和缺点。

    赞成的意见

    • 易于阅读
    • 易于书写
    • 如果可用,angular.forEach将使用es5 foreach循环。现在,我将在cons部分中讨论效率,因为foreach循环比for循环慢得多。我说这是一个专业人士,因为它是很好的一致性和标准化。

    考虑下面的两个嵌套循环,它们执行完全相同的操作。假设我们有两个对象数组,每个对象包含一个结果数组,每个结果数组都有一个字符串(或其他)的值属性。假设我们需要迭代每个结果,如果它们相等,那么执行一些操作:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    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%。因此,对于大型数据集,最好坚持使用本机for循环。
    • 无中断、继续或返回支持。continue实际上是由"意外"支持的,为了在angular.forEach中继续,您只需将一个return;语句放在类似angular.forEach(array, function(item) { if (someConditionIsTrue) return; });的函数中,这将导致它继续超出该迭代的函数。这也是由于本地forEach也不支持中断或继续。

    我相信还有很多其他的优点和缺点,请随意添加您认为合适的。我觉得,底线是,如果你需要效率,就坚持使用原生的for循环来满足你的循环需求。但是,如果你的数据集较小,并且为了可读性和可写性而放弃一些效率是可以的,那么一定要在那个坏孩子身上扔一个angular.forEach


    foreach实现(请参见jfiddle中的):

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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
      }
    );


    如果您不介意清空数组:

    1
    2
    3
    4
    5
    6
    7
    var x;

    while(x = y.pop()){

        alert(x); //do something

    }

    x将包含y的最后一个值,它将从数组中删除。您也可以使用shift(),它将给予和删除y中的第一个项目。


    jquery中有三个foreach的实现,如下所示。

    1
    2
    3
    4
    5
    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


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

    其工作原理的代码笔示例是:

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

    也见

    • 本地Array.prototype.forEach()文件。
    • 在for-each…in(MDN)中,有人解释说,for each (variable in object)不推荐作为ECMA-357(EAX)标准的一部分。
    • for…of(mdn)描述了下一种使用for (variable of object)作为和谐(ecmascript 6)建议的一部分的迭代方法。

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

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

    方法将从array[0]调用array[2]。首先,这将首先引用您甚至没有的变量,其次,您将没有数组中的变量,第三,这将使代码更大胆。看这里,我用的是:

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

    如果你希望它是一个函数,你可以这样做:

    1
    2
    3
    4
    5
    function foreach(array, call){
        for(var i in array){
            call(array[i]);
        }
    }

    如果你想打破,再多点逻辑:

    1
    2
    3
    4
    5
    6
    7
    function foreach(array, call){
        for(var i in array){
            if(call(array[i]) == false){
                break;
            }
        }
    }

    例子:

    1
    2
    3
    4
    5
    6
    7
    foreach(array, function(el){
        if(el !="!"){
            console.log(el);
        } else {
            console.log(el+"!!");
        }
    });

    它返回:

    1
    2
    3
    //Hello
    //World
    //!!!

    作为的es6:

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

    在与相关的oddities ofavoids in和使它工作的for环的像其他任何语言,和letbinds i的反对在环内的功能。

    的braces({})可以omitted当有只有一个终极的(例如在上面的例子)。


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

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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

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

    例2

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

    每个p标签得到class="blue"

    例3

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

    每隔一个p标签得到class="red">

    例4

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

    最后,前20个蓝色的P标签变为绿色。

    当使用字符串作为函数时请注意:该函数是在上下文之外创建的,应该仅在确定变量作用域的情况下使用。否则,最好传递范围更直观的函数。


    原生javascript中没有任何for each循环。您可以使用库来获取此功能(我建议使用underline.js),也可以使用简单的forin循环。

    1
    2
    3
    for (var instance in objects) {
       ...
    }

    但是,请注意,可能有理由使用更简单的for循环(请参见堆栈溢出问题,为什么在数组迭代中使用"for…in"是一个糟糕的主意?)

    1
    2
    3
    4
    5
    var instance;
    for (var i=0; i < objects.length; i++) {
        var instance = objects[i];
        ...
    }

    有几大环是一个安全的方式通过在JavaScript作为阵列,如下:

    这是最为常见的一个。完整的代码为looping布拉克

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

    而一个环,而条件是通过。它似乎是的fastest环

    1
    2
    3
    4
    5
    6
    7
    var text ="";
    var i = 0;
    while (i < 10) {
        text +=  i +") something";
        i++;
    }
    document.getElementById("example").innerHTML = text;
    1
    2
    <p id="example">
    </p>

    而我也因为/环通过一个块的代码,而威尔颤抖的条件是真的,至少一次

    1
    2
    3
    4
    5
    6
    7
    8
    var text =""
    var i = 0;
    do {
        text += i +") something";
        i++;
    }
    while (i < 10);
    document.getElementById("example").innerHTML = text;
    1
    2
    <p id="example">
    </p>

    功能loops - forEachmapfilter,也reduce(它们用于循环通过的功能,但如果你需要做一些与你的阵列,等等。

    1
    2
    3
    // 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});
    1
    2
    <p id="example">
    </p>

    更多的信息和关于在arrays功能编程的例子,看看在博客发布在JavaScript编程功能:地图,滤波和减少。


    ecmascript5(在JavaScript的版本与arrays)工作。

    每一个项目iterates foreach -通过在阵列和做你需要与每个项目。

    1
    2
    3
    4
    5
    6
    7
    8
    ['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

    在的情况下,更多的兴趣在使用的一些inbuilt操作在阵列特征。

    这creates地图的一个新的研究结果与callback阵列的功能。这种方法是很好的大,是当你需要使用的阵列的元素的格式。

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

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

    减少-作为它的名字说reduces阵列由一个单一的价值大的给定的功能通过电话在currenct元和结果公布的前一执行。

    1
    2
    3
    4
    5
    6
    7
    [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

    每一个returns真或假-如果在所有的元素,通过在callback阵列测试功能。

    1
    2
    3
    4
    5
    6
    7
    // 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。

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

    // Output: [2,4,6]

    希望这将是有用的。


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

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

    这是因为当按数组顺序执行的任何回调返回true时,some立即返回true,从而使其余回调执行短路。原始答案参见数组原型


    我还想将它添加为一个反向循环的组合,并为希望使用此语法的人提供上面的答案。

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

    赞成的意见:

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

    欺骗:

    当引用为假-假(未定义等)时,这将中断。不过,它可以作为一种优势。然而,它会使阅读变得有点困难。而且,根据浏览器的不同,它可以"不"优化,以比原来的更快地工作。


    jQuery方式使用$.map

    1
    2
    3
    4
    5
    6
    7
    8
    9
    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];


    使用带有ES6破坏和扩展运算符的循环

    破坏和使用spread操作符已经被证明对ES6的新用户非常有用,因为它更具人类可读性/审美性,尽管一些JavaScript老手可能认为它杂乱无章,但年轻人或其他人可能会发现它很有用。

    The following examples will use for...of statement and .forEach method.

    Examples 6, 7 and 8 can be used with any functional loops like .map, .filter, .reduce, .sort, .every, .some, for more information about these methods check out the Array Object.

    例1:normal for...of循环-这里没有技巧。

    1
    2
    3
    4
    5
    let arrSimple = ['a', 'b', 'c'];

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

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

    1
    2
    3
    4
    5
    6
    7
    8
    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);

    }

    例3:与keyvalue循环

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    // 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);
    }

    示例4:get object properties inline

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    let arrWithObjects = [{
        name: 'Jon',
        age: 32
      },
      {
        name: 'Elise',
        age: 33
      }
    ];

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

    示例5:获取所需的深度对象属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    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);
    }

    例6:例3是否与.forEach一起使用?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    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);
    });

    例7:例4是否与.forEach一起使用?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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)
    });

    例8:例5是否与.forEach一起使用?

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    let arrWithObjectsWithArr = [{
        name: 'Jon',
        age: 32,
        tags: ['driver', 'chef', 'jogger']
      },
      {
        name: 'Elise',
        age: 33,
        tags: ['best chef', 'singer', 'dancer']
      }
    ];

    arrWithObjectsWithArr.forEach(({
      name,
      tags: [firstItemFromTags, ...restOfTags]
    }) => {
      console.log(name, firstItemFromTags, restOfTags);
    });


    一个方法closest到你的想法会使用其中一个大Array.forEach()接受clojure wich executed功能将为每个元素的阵列。

    1
    2
    3
    4
    5
    6
    myArray.forEach(
      (item) => {
        // do something
        console.log(item);
      }
    );

    另一个可行的方式将大Array.map()作品使用在相同的方式,但也mutates每个元素和returns它像:

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

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


    通常的语法doesnt lambda IE工作在10或以下。

    我通常使用的

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    [].forEach.call(arrayName,function(value,index){
        console.log("value of the looped element" + value);
        console.log("index of the looped element" + index);
    });


    If you are a jQuery Fan and already have a jQuery file running, you should reverse the positions of the index and value parameters

    $("#ul>li").each(function(**index,value**){
        console.log("value of the looped element" + value);
        console.log("index of the looped element" + index);
    });

    您可以这样调用foreach:

    1
    2
    3
    4
    5
    6
    let Array = [1,3,2];

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

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

    输出:

    1
    2
    3
    1    
    3    
    2

    解释:

    foreach在原型类中。您也可以将其称为array.prototype.foreach(…);

    原型:https://hacker noon.com/prototype-in-javascript-5bba2990e04b

    您还可以在这样的数组上进行更改:

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


    如果要循环使用箭头函数的对象数组:

    1
    2
    3
    4
    5
    [cc lang="javascript"]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');
    })

    < /代码>


    总结:

    在迭代数组时,我们通常希望实现以下目标之一:

  • 我们要迭代数组并创建新数组:

    Array.prototype.map

  • 我们希望遍历数组,而不创建新数组:

    Array.prototype.forEachfor..of回路

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

    创建新阵列:Map

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

    1
    2
    3
    4
    5
    6
    7
    8
    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)。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    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循环遍历数组的每个元素(或任何其他不可重复的对象)。其工作方式如下:

    1
    2
    3
    4
    5
    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循环将只遍历数组元素。例如:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    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);
    }


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

    1
    theArray.map(instance => do_something);

    这样,您将为将来的操作生成新的数组,并跳过任何不需要的副作用。


    1
    2
    3
    4
    5
    6
    7
    // 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
    });


    如果你有一个大的,大量使用iterators阵列你应该获得一些效率。JavaScript是一iterators一定产权的收藏(如mapSetStringArray)。甚至,for..ofiterator下使用该罩。

    提高效率iterators由肝脏产生不利影响的items不能说你在一个列表的一个在一个时间,如果他们是作为一个流。是什么使得它traverses iterator如何安全的特殊集合。其他loops需要load收集起来的整个前在大iterate超过它的顺序,而只需要知道的安全iterator当前打印位置的集合。

    你当前的Access项目的iterator next由电话的方法。该方法将返回一value的当前的项目和一个大的boolean表示当你已经达到了最后的集合。以下是一个例子创建的安全的安全iterator从阵列。

    regular阵列变换的方法使用大iterator values(),像这样:

    1
    2
    3
    4
    5
    6
    7
    8
        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());

    你可以同时使用你的regular阵列变换大iterator Symbol.iterator,像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    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());

    你可以变换你的regular也大iteratorArray安全,像这样:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    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}

    注:

    • iterators是exhaustible性质。
    • 对象是由不iterable安装默认。使用的情况下,而不是在for..in,因为作品的价值与它的钥匙。

    在这里你可以阅读更多关于iteration protocol


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


    我来自Python,我发现这样更清楚。数组是数组,实例是数组的元素

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

    1
    2
    3
    4
    for( instance in theArray)
    {
      console.log("The instance",instance);
    }

    比较:

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

    但在一天结束的时候,他们都在做同样的事情


    您可以使用for each()API(由javascript提供),它接受函数作为回调,并为数组中的每个元素运行一次。

    https://fullstackgeek.blogspot.com/2019/01/arrays-in-javascript-part-2.html


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

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

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

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