再探JS数组原生方法—没想到你是这样的数组
第一题:
What is the result of this expression? (or multiple ones)
[ [3,2,1].reduce(Math.pow), [].reduce(Math.pow) ]
an error
[9, 0]
[9, NaN]
[9, undefined]
在Node环境中可以自行执行上面的表达式,结果会产生TypeError: Reduce of empty array with no initial value
也就是说在不能在空数组上调用不带初始参数的reduce方法,可以像下面这样调用,增加一个初始参数
1 | console.log([ [3,2,1].reduce(Math.pow), [].reduce(Math.pow,1)])//输出[9,1] |
第二题:
What is the result of this expression? (or multiple ones)
var ary = [0,1,2];ary[10] = 10;ary.filter(function(x) { return x === undefined;});
[undefined × 7]
[0, 1, 2, 10]
[]
[undefined]
Array.prototype.filter is not invoked for the missing elements.
由上面的结果可以得知,“稀疏数组”中丢失的元素并不会唤起filter方法的调用,但是如果你打印出稀疏元素
1 | console.log(ary[5]); //undefined |
结果确实是undefined。打印整个数组看一下:
1 | console.log(ary) //[ 0, 1, 2, , , undefined, , , , , 10 ] |
所以这种通过直接给ary[10]赋值的方式产生的数组并不将未赋值的地方变成真正的undefined。
创建“稀疏数组”的方法也不只这一种,那么其他方法会不会也是这种情况呢。
1 2 3 4 | var ary = [0,1,2]; ary.length = 10; console.log(ary) //[ 0, 1, 2, , , , , , , ] console.log(ary.filter( function (x) { return x === undefined;})); //[] |
从上例可以看到使用设置arr.length的方法创建的稀疏数组也是一样的情况。
1 2 3 4 5 6 | var ary = Array(10); ary[0]=0; ary[1]=1; ary[2]=2; console.log(ary) //[ 0, 1, 2, , , , , , , ] console.log(ary.filter( function (x) { return x === undefined;})); //[] |
从上可以看出通过 ary = Array(10);创建的稀疏数组同样出现这样情况。
接下来拓展一下,直接将undefined赋值给ary[5]
1 2 3 4 5 | var ary = [0,1,2]; ary[5]=undefined; //直接将undefined赋值给ary[5] ary[10] = 10; console.log(ary) //[ 0, 1, 2, , , undefined, , , , , 10 ] console.log(ary.filter( function (x) { return x === undefined;})); //[ undefined ] |
从结果中可以看出只有ary[5]通过了筛选。
稀疏数组的这种特性在数组的map方法中是否存在呢,接着看第三题。
第三题:
What is the result of this expression? (or multiple ones)
var ary = Array(3);ary[0]=2;ary.map(function(elem) { return '1'; });
[2, 1, 1]
["1", "1", "1"]
[2, "1", "1"]
other
The result is ["1", undefined × 2]
, as map
is only invoked for elements of the Array
which have been initialized.
官网给出了上面的 解析,在浏览器中运行就是上面的结果,我在Node环境中显示的结果是[ '1', , ]。不管怎么样都说明了在稀疏元素上并没有唤起调用map的回调函数。
2016-7-20补充:那么有没有办法让稀疏数组唤起调用map或者上一题的filter方法呢?看完下面的例子大概就清楚了
1 2 3 4 5 | var a = Array(10).join( "," ).split( "," ).map( function (item, index) { return index; }); console.log(a); |
通过join方法把它转成字符串,然后,再通过split方法把字符串转成数组,这时候,它就拥有10个值为空的元素了,然后,再通过map函数,改变这些元素的值即可。
第四题:
What is the result of this expression? (or multiple ones)
var x = [].reverse;x();
[].reverse will return this and when invoked without an explicit receiver object it will default to the default this AKA window
reverse 方法颠倒数组中元素的位置,并返回该数组的引用。出题者的意图是该方法会返回this,然后在全局环境中这个this就是window,而实际上经过我测试,在谷歌浏览器上显示错误:
Uncaught TypeError: Array.prototype.reverse called on null or undefined(…)
在Node环境中显示
TypeError: Array.prototype.reverse called on null or undefined
可以看出实际上 var x = [].reverse返回的是对数组reverse方法的引用,直接调用的话会出错。可以使用call方法调用
1 2 3 4 | var x = [].reverse; var arr=[1,2,3]; console.log( x.call(arr)); //[ 3, 2, 1 ] |
第五题:
What is the result of this expression? (or multiple ones)
[,,,].join(", ")
JavaScript allows a trailing comma when defining arrays, so that turns out to be an array of three undefined.
因为javascript 在定义数组的时候允许最后一个元素后跟一个,
, 所以这是个长度为三的稀疏数组(这是长度为三, 并没有 0, 1, 2三个属性哦),同理
1 2 | var arr=Array(3); console.log(arr.join( ", " ) ) //, , |
参考: