我正在学习如何使用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"]
谢谢!
答案 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
混淆。