最近我正在接受面试,有人让我参加考试:
var array = [1, 2, 3];
array[10] = 10;
alert(array.filter( n => n === undefined));
我确信这会警告一个7x未定义的数组,或者这些行之类的东西。
然而,它输出一个空数组,如长度为0的数组。
对我而言,这是令人困惑的。有人可以帮我解释为什么会这样吗?
答案 0 :(得分:8)
未访问已删除或未初始化(在稀疏数组上)项目。
<强>描述强>
var array = [1, 2, 3, , , , , , , , 10]; console.log(array.filter((n, i) => (console.log(i), n === undefined)));
按升序为数组中的每个元素执行一次提供的回调。对于已删除或未初始化的索引属性(即在稀疏数组上),不会调用它。
.as-console-wrapper { max-height: 100% !important; top: 0; }
{{1}}
答案 1 :(得分:1)
如果知道内部帮助,Array.prototype.filter
(forEach,map,reduce)也会像这样排序(省略边界/角落检查):
Array.prototype.filter = function(fun/*, thisArg*/) {
var arr = Object(this);
var len = arr.length;
var res = [];
for (var i = 0; i < len; i++) {
if (i in arr) {
var val = arr[i];
if (fun.call(thisArg, val, i, arr)) {
res.push(val);
}
}
}
return res;
}
关键是if
循环中的for
语句:
if (i in arr) { ... }
很明显,数组项目是“可过滤的”,必须明确声明/初始化这些项目并在key
中关联prop
/ arr
,这不适用于其他答案指出sparse array
。
<子>
注意:如果在控制台中运行var array = [1, 2, 3]; array[10] = 10;
,则生成的稀疏数组如下所示:
Array[11]
0: 1
1: 2
2: 3
10: 10
length: 11
__proto__: Array[0]
答案 2 :(得分:0)
考虑到您设置的箭头功能,因为过滤器仅返回未定义的项目,但没有任何项目未定义,因此结果为空数组。但我想我知道你在哪里感到困惑。
array[10] = 10
不设置数组的长度。它将特定项设置为值10.因此,在此行之后,您将拥有一个包含4个元素的数组:1,2,3和... 10.
在数组中,您可以设置特定值的索引。如果省略它,它只会将1添加到最后一个索引。试试这个:
var array = [1, 2, 3];
array[10] = 10;
array.forEach( (value, index) => console.log(value, index));
JSFiddle:https://jsfiddle.net/eetmkd95/1/
你会看到它打印出来:
1 0
2 1
3 2
10 10
为什么?因为如果你没有指定索引,它将基于+1增量生成一个索引,如果你指定,那么它会把你的值放在那个索引中。但是你要指定INDEX,而不是长度。
现在试试这个:
var array = [1, 2, 3];
array.length = 10;
array[8] = 10;
array.forEach( (value, ix) => console.log(value, ix));
console.log(array.length);
这怎么可能? length属性报告10而forEach只打印4行?这是因为a)forEach只显示实际存在于数组中并具有数字索引的项目,而b)长度不是非常可信。它仅适用于数字索引,并且仅当您未将其设置为更高的值时(如果您将其设置为较低的值,则它可以工作)。如果您使用字符串作为索引,它也不起作用。例如:
var array = [1, 2, 3];
array['myString'] = 10;
array.forEach( (value, ix) => console.log(value, ix));
console.log(array.length);
打印:
1 0
2 1
3 2
3
希望我澄清一点:)
你可以从Kyle Simpson的优秀系列丛书“你不懂JS”中深入理解这一点。关于这一点的部分在“Types&amp; Grammar”一书中,第44页,标题为“Array(..)”