问题描述
我搞砸了JavaScript的push和pop函数的性能。
我有一个名为arr
的数组。
当我运行这个:
for (var i = 0; i < 100; i++) {
for (var k = 0; k < 100000; k++) {
arr.push(Math.ceil(Math.random() * 100));
arr.pop();
}
}
我得到的时间为251.38515999977244毫秒(我正在使用performance.now()函数)。
但是,当我运行自定义推送并弹出时:
Array.prototype.pushy = function(value) {
this[this.length] = value;
}
Array.prototype.poppy = function() {
this.splice(-1, 1);
}
for (var i = 0; i < 100; i++) {
for (var k = 0; k < 100000; k++) {
arr.pushy(Math.ceil(Math.random() * 100));
arr.poppy();
}
}
时间是1896.055750000014毫秒。
谁能解释为什么两者之间有如此大的差异?
对于那些担心时差的人。 我进行了100次测试,并计算了平均时间。 我做了5次,以确保没有任何空闲时间。
1楼
因为内置函数是用浏览器所用的任何语言(可能是C ++)编写并进行编译的。 自定义函数用Javascript编写并进行了解释。
通常,解释型语言比编译型语言要慢得多。 人们通常不会用Javascript注意到这一点,因为在大多数情况下,您只能在人机交互之间执行几行JS(这总是最慢的部分)。
如此处所述,在紧密循环中运行JS可以突出显示两者之间的区别。
2楼
原因是内置功能经过专门设计和优化以执行特定功能。 当使用内置功能时,浏览器会采用任何可能的快捷方式,而在自定义功能中识别起来可能不那么快捷。 例如,在您的实现中,函数每次调用函数时都需要获取数组长度。
Array.prototype.pushy = function(value) {
this[this.length] = value;
}
但是,仅通过使用Array.prototype.push
,浏览器便知道其目的是在数组上附加一个值。
虽然浏览器可能会以不同的方式实现功能,但我高度怀疑是否需要为每次迭代计算数组的长度。