forEach on a' new Array'没有做我期望的事

时间:2014-04-24 23:19:21

标签: javascript arrays higher-order-functions

我正在学习如何使用JS高阶函数(map,forEach,reduce等),并且偶然发现了混乱。我试着写一个简单的范围'功能,但似乎不能填充我的输出数组。这是目标:

range(1, 4) // [1, 2, 3, 4]

我得到了这个:

[undefined × 4]

这是我的代码:

 function range(num1, num2) {
      var rangeArr = new Array((num2 + 1) - num1);
      return rangeArr.map(function(e, i, arr) {return arr[i] = num1 + i});
    }

我在这里缺少什么?据我所知,问题似乎与我使用“新阵列”的方式有关,但除此之外,我已经迷失了。

哦,这是让我感到困惑的部分。这很好用:

function bleck() {
    var blah = [1, 2, 3, 4];
    var x = 'wtf';
    return blah.map(function(e, i, arr) {return arr[i] = x})
}

["wtf", "wtf", "wtf", "wtf"]

谢谢!

4 个答案:

答案 0 :(得分:4)

forEach方法迭代数组的索引。有趣的是,当您通过new Array(n)创建新数组时,它包含根本没有索引。相反,它只是设置其.length属性。

> var a = new Array(3);
> console.info(a)
[]
> console.info([undefined, undefined, undefined])
[undefined, undefined, undefined]

MDN描述了forEach,并具体说明了:

  

forEach为每个元素执行一次提供的回调   具有指定值的数组。对于具有的索引,不会调用   已被删除或删除

这是一种巧妙的技术,可以获得一个空的但现有的索引数组。

var a = Array.apply(null, Array(3));

这是有效的,因为.apply“将”省略的元素扩展为正确的参数,结果最终会像Array(undefined, undefined, undefined)一样。

答案 1 :(得分:1)

数组定义为4个entires,每个entires都是未定义的。

Map不会迭代未定义的entires,它会跳过它们。

  

仅对已分配的数组的索引调用回调   值;对于未定义的索引,不会调用它   已删除或从未分配过值。

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map

答案 2 :(得分:1)

当您创建new Array(x)时,它正在创建所谓的稀疏数组,这可能会有所不同,如您所见,某些浏览器会说[undefined x 20,"foo", undefined x 5]如果您只设置一个值,我相信它不会迭代这些值。

答案 3 :(得分:0)

问题是map不会迭代未定义的条目(*)。

我建议改为使用for循环:

var rangeArr = new Array((num2 + 1) - num1);
for(var i=0; i<=num2-num1; ++i)
    rangeArr[i] = num1 + i;
return rangeArr;

(*)使用未定义的条目,我的意思是rangeArr.hasOwnProperty(i) === false,不要与rangeArr[i] === void 0混淆。