【问题标题】:Ways to iterate over undefined in Arrays遍历数组中未定义的方法
【发布时间】:2016-10-28 03:06:51
【问题描述】:

我最近发现.map 不会迭代未定义的由孔数组创建,这些数组的各个索引已定义,但有些未定义:

// Holed
var array = [];
array[0] = 1;
array[2] = 3;
array // => [1, undefined, 3];

// Not Holed
var array = [1, undefined, 3];
array // => [1, undefined, 3]; The "same" as Holed

说到迭代,这两个应该是相同的,以不同方式定义的数组被不同地迭代(见第一句)

这是我的问题,

  1. 有什么方法可以遍历有孔的数组吗?
  2. 我怀疑这些的确切字节实际上是不同的,而这种奇怪的行为是由于JavaScript如何显示这些未定义的值,而不是undefined。我对么?这种异常现象有什么潜在的解释吗?

非常欢迎任何帮助。谢谢!

【问题讨论】:

  • 您可以使用普通的 for 循环进行迭代。不同之处在于第一个数组中的属性1 从未设置过,而在第二个数组中却有。
  • 您可以使用其迭代器将有孔数组转换为无孔数组:const arrayWithoutHoles = [...array]; 或以特别方式[...array].map(f)
  • 先过滤掉vals? array.filter(function (f) {return f != undefined})
  • @James111 先试试你的代码?
  • 试试这个:var holed = []; holed[0] = 0; holded[2] = 2; console.log(Object.keys(holed)); var un = [ 0, undefined, 2 ]; console.log(Object.keys(un));

标签: javascript arrays


【解决方案1】:

有什么方法可以遍历空洞数组吗?

大多数(全部?)内置 Array.prototype 函数会跳过稀疏数组中的漏洞。

这意味着,如果您想获取缺失索引的 undefined 值 - 您需要先将该数组转换为非稀疏数组。

在 ES2015 的帮助下,您可以使用数组迭代器。最短的方法是使用数组扩展语法:

[...array]

然后您可以对其应用映射运算符[...array].map(handler)

我怀疑它们的确切字节实际上是不同的,这种奇怪的行为是由于 JavaScript 如何显示这些未定义的值,而不是未定义的。我对么?这种异常有什么潜在的解释吗?

你是对的,它没有明确地保存undefined 值。由于 JS 中的数组实际上是所谓的“内在对象”(或更短的 - 只是对象),它们的索引只是这些对象的属性。因此,当您跳过索引时 - 该属性根本没有设置并且不存在。

这与访问不存在的对象属性相同:

var o = {};
o.foo // undefined

【讨论】:

    【解决方案2】:

    1.如下:

    // Holed
    var array = [];
    array[0] = 1;
    array[2] = 3;
    array // => [1, undefined, 3];
    for(var i=0;i<array.length;i++) {
      console.log(array[i])
    }
    1. map,every,forEach,等等都有同样的表现。回调

    对于数组的缺失元素(即从未设置、已删除或从未赋值的索引)不会调用它。

    Read more.

    【讨论】:

    • 这会失败,因为数组长度为 2,所以 i 将采用值 0, 1array[1] 从未定义过,此代码不会执行已定义的 array[2]
    • @Tibrogargan 数组长度肯定是 3。
    • @zerkms 是的,刚刚检查过。有趣的。 Object.keys(array) 将返回 2 个元素。 JavaScript 认为第三个键到底是什么?
    • @Tibrogargan 它不计算元素的数量 - 它只是在每次修改数组时维护 .length 属性值并将其设置为 maxIndex + 1
    • @Tibrogargan 这取决于该术语的定义。对我来说,“洞”只是没有初始化的成员。
    【解决方案3】:

    我只是偶然发现了这一点,这些答案似乎都不合适。当我使用 for( x of array) 我会得到适当数量的循环,但无法更改元素(未定义且无索引)。

    回到谷歌,下一个答案ref提供了这个作为解决方案:

    for(const [key, value] of array.entries()) {
       console.log(key+" : "+value)
    }
    

    在数组上使用entries 可以让我们获得键/值对,甚至是未定义的元素

    【讨论】:

      【解决方案4】:

      关于你的第二个问题:

      我怀疑它们的确切字节实际上是不同的,并且 这种奇怪的行为是由于 JavaScript 如何显示这些值 未定义,未定义。我对么?有没有 对此异常的基本解释?

      这不是 JavaScript(即 ECMAScript)显示值的方式。我希望你得到:

      array // => [1, undefined, 3];
      

      在 Firefox 等浏览器的控制台中。对控制台显示的内容要非常小心,因为它们倾向于提供帮助而不是严格正确。

      您创建了一个数组,如下所示:

      var array = [];
      array[0]  = 1;
      array[2]  = 3;
      

      那么等价的数组字面量是:

      var array = [1,,3];
      

      这使得缺少中间元素更加明显。此外,内置的 Array.prototype.toString 方法将使用 join 以便返回相同的结果:

      array.toString() // [1,,3]
      

      所以不,您看到的不是 JavaScript 本身的结果,而是您的特定浏览器或实现的控制台的结果。

      另外,不同的控制台给出不同的结果,在 Safari 中我得到:

      [1,,3] // [1, 2: 3] (3) = $2
      

      【讨论】:

        【解决方案5】:

        有一种方法可以使用像forEach() 这样的内置方法来填充有孔的数组。例如,假设我想用字符串“bonjour”填充这样一个数组的孔:

        var input = [];
        input[0] = 1;
        input[2] = 3;
        console.log(input); // [ 1, , 3 ]
        input.map((item, index, arr) => {
            if (!arr[index +1] && index < arr.length-1) arr[index+1] = "bonjour";
        });
        console.log(input); // [ 1, 'bonjour', 3 ]
        

        【讨论】:

          猜你喜欢
          • 2020-08-25
          • 2017-02-08
          • 1970-01-01
          • 2021-10-23
          • 1970-01-01
          • 1970-01-01
          • 2015-09-02
          • 2012-08-25
          • 1970-01-01
          相关资源
          最近更新 更多