嵌套for循环和多维数组

时间:2018-02-24 00:47:27

标签: javascript arrays loops

我试图了解嵌套for循环如何在JavaScipt中使用多维数组,我有点卡在一点上。 使用股票示例

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

这输出1 2 3 4 5 6这是我的预期。 但是,如果我在外部数组的末尾添加数字:

var arr = [[1,2], [3,4], [5,6], 7, 8];
for (var i=0; i < arr.length; i++) {
    for (var j=0; j < arr[i].length; j++) {
        console.log(arr[i][j]);
    }
}

我仍然得到1 2 3 4 5 6的相同输出? ? 我很困惑为什么7&amp;循环没有拾取8。有趣的是,如果我改用字符串:

var arr = [["a","b"], ["c","d"], "y", "z"];
for (var i=0; i < arr.length; i++) {
    for (var j=0; j < arr[i].length; j++) {
        console.log(arr[i][j]);
    }
}

输出是b c d y z,这是我的预期。为什么字符串的行为不同?

3 个答案:

答案 0 :(得分:2)

正如其他人所提到的,你的内部循环就是迭代顶级(非嵌套数组)中的数组。它假设顶级数组中的所有元素都是嵌套数组,但实际情况并非如此。 (在尝试迭代之前,您需要确保拥有一个数组。)由于顶层的78不是数组,arr[i].length返回undefined对于数字,但字符串是“数组类似”对象,并且具有length属性。字符串"y"的{​​{1}}为length,因此内部循环起作用,因为它从零开始并获取{{1}的字符串“数组”中位置0处的字符},这是1

但是,当我们现在有 Array.forEach() 时,这是一个不使用传统"y"循环和数组的好理由,这样就无需手动管理索引和允许我们直接访问被枚举的值,而不必担心索引。

"y"

哦,顺便说一下,我意识到这不是你所要求的,但就像一个FYI,这是一种获取所有值而没有任何循环的方法:

for

答案 1 :(得分:1)

  

为什么字符串的行为会有所不同?

因为字符串被视为字符数组。

JavaScript字符串存储一系列字符,如“John Doe”。可以使用数组索引访问每个字符,并且还具有length方法来获取字符串的大小。因此,为什么"y", "z"有效但7, 8无效,因为它们不是数组。

答案 2 :(得分:0)

以下是现代Javascript中的内容。

关于循环,所有值可以分为“可迭代”和“不可迭代”。 Iterable是值得你可以...迭代 - 使用for..of循环。

for (let item of someIterableThing)
    // use item

(你使用裸for循环 - for(var i...i < length) - 用于迭代,因为并非每个iterable都有length和索引。)

相反,如果你使用不可迭代的事物for...of,你会收到错误。

数组和字符串是可迭代值的示例,数字是不可迭代的。所以,当你有

[ [1,2], [3,4], "foobar" ]

此数组中的所有项都是可迭代的,您的嵌套循环将起作用。但是,在

[ [1,2], [3,4], 999]

最后一项是不可迭代的,嵌套循环将失败。

没有内置的方法来判断一个未知值是否可迭代,你必须为此编写一个函数:

 let isIterable = x => x && x[Symbol.iterator]

(见the dedicated topic)。

然后,您可以安全地使用嵌套循环:

for (let item of array)
    if (isIterable(item))
        for (let subItem of item)
            console.log(subItem)
    else
        console.log(item)

作为旁注,网上有很多关于Javascript的过时信息。这种语言在不断发展,5年前的事情很好,现在被认为是不好的做法。不幸的是,大多数教程,书籍和教师都没有跟上,并且仍在推广旧的做法,比如使用裸for循环。

(因为人们问为什么确实裸for个循环是坏的,请考虑这个例子:

您有一个数组text,其中包含处理此数组的字符串和多个函数。程序员A以老式的方式编写这些函数:

for (var i = 0; i < text.length; i++)  
     do_something_with(text[i]) // ;(

程序员B以现代方式编写它们:

for (let str of text)  
     do_something_with(str) // :)

现在,text变得越来越大,不再适合记忆。因此,系统架构师决定用一个只能一次生成一个字符串的可流式文件对象替换它。程序员A现在必须重写他的所有100个函数以适应新的界面:

  for (var file = TextFile; !file.eof(); file.getNext())
      do_something_with(file.currentLine)

涉及许多疼痛,抽搐和头痛。

程序员B只是喜欢她的假期。)