我只是在学习如何使用JS高阶函数(map、forEach、reduce等),却陷入了困惑。我试图编写一个简单的"range"函数,但似乎无法填充我的输出数组。这就是目标:
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"]
谢谢!!
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)
类似。
数组由4个整数定义,每个整数都未定义。
Map不会迭代未定义的实体,而是跳过它们。
回调仅对已分配的数组的索引调用价值观对于未定义的索引,即已被删除或从未分配过值。
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map
当您创建一个new Array(x)
时,它正在创建一个所谓的稀疏数组,它的行为可能有点不同,正如您所看到的,如果您只设置一个值,一些浏览器会说[undefined x 20,"foo", undefined x 5]
,我相信它不会迭代这些值。
问题是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
混淆。