关于数组的性能
Javascript 批量创建数组的方法,为了衡量它们的性能,我分别使用不同的方法创建一个长度为 100000 的数组,且键和值相等。
定义了下面这个函数用来测量创建数组所耗费的时间:
function time(fn) {
var start = Date.now();
fn.call(this);
var end = Date.now();
console.log((end - start) + 'ms');
}
使用join和split:
// 24ms
time(function() {
var arr = new Array(100000);
arr = arr.join(' ').split('').map((v, i) => i);
})
该方法把大量时间耗费在了map操作上,去掉map上操作只有2ms。
// 2ms
time(function() {
var arr = new Array(100000);
arr = arr.join(' ').split('');
})
使用apply
// 25ms
time(function() {
Array.apply(null, { length: 100000 }).map((v, i) => i)
})
这里用到了一个{ length: 100000 }伪数组,NodeList和arguments都是伪数组(array-like object),它们都不是真正意义上的数组,而是带有"length属性"并且同时具备"索引属性"的对象,不能直接使用数组的那些方法,而apply和call却可以接受这种伪数组。我们平时在用的Array.prototype.slice( arguments)就是基于这个原理。
这里把长度为100000的伪数组传递给Array函数,构造出了一个长度为100000的数组,然后再用map赋值。为什么不直接Array(100000)生成数组,这是因为通过Array(100000)生成的数组每个值都为undefined,无法通过map遍历。
使用Array.from()
可以将伪数组直接转换为数组
// 20ms
time(function() {
Array.from( {length: 100000}, (v, i) => {return i;} )
})
如果把伪数组换成数组,速度慢了很多。
// 29ms
time(function() {
Array.from( new Array(100000), (v, i) => {return i;} )
})
使用Array.fill()
先使用Array.fill填充数组,之后再通过map挨个赋值。
// 23ms
time(function() {
Array(100000).fill(1).map((v, i) => {return i;})
})
使用for循环
// 6ms
time(function() {
var arr = [];
for (var i = 0; i< 100000; ++i) {
arr.push(i);
}
})
发现还是原始的for循环速度比较快,其他的几个方法速度都差不多。
但是for循环写起来也相对其他的方法较为麻烦,一句话就能搞定的时候需要三句话才能搞定。
所以,如果对性能没有太大要求的话(毕竟在实际开发中也不会有100000那么大的数组),使用apply和Array.from最方便。