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

时间:2015-03-10 21:01:02

标签: 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

Dense Arrays

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

[undefined, undefined, undefined]

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

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'

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

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'

所以我的问题是:

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

1 个答案:

答案 0 :(得分:4)

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

这些函数explicitly documented以这种方式执行。两个数组都是可迭代的,但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
  
      
  1. 差异的原因是什么?
  2.   

据推测,明确决定省略不存在的指数

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

您可以使用以下内容:

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

RE:您的评论

  

为什么[,,,]没有索引但[undefined,undefined,undefined]确实存在原因。

必须是一个理由,这就是它们的构建方式。一个有钥匙,另一个没有钥匙。

查找

Object.keys(Array(3)) // => []
Object.keys(['a','b']) // => ["0", "1"]