为什么`.forEach`在密集数组上工作但在稀疏数组上不工作?

pse*_*ant 5 javascript arrays

我试图理解'空'稀疏数组(例如new Array(3))和等效'空'密集数组(具有3个未定义条目的数组)之间的区别.

我可以用这两种方式创建一个包含3个未定义值的数组:

var sparse = new Array(3);
// or
var sparse = [,,,];

var dense = Array.apply(null, Array(3)); // See dense array link below
Run Code Online (Sandbox Code Playgroud)

密集阵列

如果我为其中任何一个执行console.log,结果是:

[undefined, undefined, undefined]
Run Code Online (Sandbox Code Playgroud)

如果我遍历每个数组以将其与另一个数组进行比较,它们将严格匹配:

console.log(sparse.length === dense.length);

// true

for (var i = 0; i < dense.length; i++) {
  console.log(i +':'+ (dense[i] === sparse[i]));
}

// '0:true'
// '1:true'
// '2:true'
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用.forEach(或map,reduce等),那么回调将永远不会在稀疏数组上调用,但会在密集数组上调用三次:

sparse.forEach(function(val,i){
   console.log(i +':'+ val);
});

// Nothing. No-op.

dense.forEach(function(val,i){
   console.log(i +':'+ val);
});

// '0:undefined'
// '1:undefined'
// '2:undefined'
Run Code Online (Sandbox Code Playgroud)

所以我的问题是:

  1. 如果它们都具有相同的长度,索引和值,那么一个是可迭代的,而另一个不是?
  2. 差异的原因是什么?
  3. 确定数组是稀疏还是密集的最佳方法是什么?

mea*_*gar 4

  1. 如果它们都具有相同的长度、索引和值,那么如何一个可迭代而另一个不可迭代?

这些函数被明确记录为以这种方式执行。两个数组都是可迭代的,但forEach/ map/etc 显式跳过不在数组中的索引:

var sparse = new Array(3);
var dense = Array.apply(null, Array(3)); // See dense array link belo

1 in sparse; // false
1 in dense; // true

// Sparse can still be iterated over
sparse[100] = 'a'
sparse.forEach(function (n, i) { console.log(n, i) }); // a 100
Run Code Online (Sandbox Code Playgroud)
  1. 差异的原因是什么?

大概已做出明确决定省略不存在的索引

  1. 确定数组是稀疏还是密集的最佳方法是什么?

您可以使用以下内容:

function isSparse(array) {
  for (var i = 0; i < array.length; ++i) {
    if (!i in array)
      return true;
  return false;
}
Run Code Online (Sandbox Code Playgroud)

回复:您的评论

[,,,] 没有索引而 [undefined, undefined, undefined] 有索引,这肯定是有原因的。

不一定原因,这就是它们的构建方式。一个有钥匙,另一个没有。

看:

Object.keys(Array(3)) // => []
Object.keys(['a','b']) // => ["0", "1"]
Run Code Online (Sandbox Code Playgroud)