Javascript 为什么自定义函数比内置函数慢?

Javascript 为什么自定义函数比内置函数慢?,javascript,Javascript,我对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(); } } for(变量i=0;i

我对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();
  }
}
for(变量i=0;i<100;i++){
对于(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();
    }
 }
Array.prototype.pushy=函数(值){
this[this.length]=值;
}
Array.prototype.poppy=函数(){
这个。拼接(-1,1);
}
对于(变量i=0;i<100;i++){
对于(var k=0;k<100000;k++){
arr.pushy(Math.ceil(Math.random()*100));
阿罂粟();
}
}
时间为1896.055750000014毫秒

有人能解释为什么这两者之间有如此巨大的差异吗


给那些担心时差的人。我进行了100次测试,计算了平均时间。我这样做了5次,以确保没有任何离奇的时间。

因为内置函数是用浏览器编写的任何语言(可能是C++)编写和编译的。自定义函数是用Javascript编写并解释的

一般来说,解释语言比编译语言慢得多。Javascript通常不会注意到这一点,因为在大多数情况下,在人类交互之间只执行几行JS(这总是最慢的部分)


在一个紧凑的循环中运行JS,就像您在这里所做的那样,突出了区别。

因为内置函数是用浏览器所用的任何语言(可能是C++)编写和编译的。自定义函数是用Javascript编写并解释的

一般来说,解释语言比编译语言慢得多。Javascript通常不会注意到这一点,因为在大多数情况下,在人类交互之间只执行几行JS(这总是最慢的部分)


在一个紧密的循环中运行JS,正如您在这里所做的那样,突出了区别。

原因是内置函数是专门为执行特定功能而设计和优化的。当使用内置功能时,浏览器会采用任何可能无法在自定义功能中快速识别的快捷方式。例如,在您的实现中,每次调用函数时,函数都需要获取数组长度

Array.prototype.pushy = function(value) {
  this[this.length] = value;
}

但是,通过简单地使用
Array.prototype.push
,浏览器知道其目的是将值附加到数组中。虽然浏览器可能以不同的方式实现该功能,但我高度怀疑是否需要为每次迭代计算数组长度。

原因是内置函数是专门为执行特定功能而设计和优化的。当使用内置功能时,浏览器会采用任何可能无法在自定义功能中快速识别的快捷方式。例如,在您的实现中,每次调用函数时,函数都需要获取数组长度

Array.prototype.pushy = function(value) {
  this[this.length] = value;
}

但是,通过简单地使用
Array.prototype.push
,浏览器知道其目的是将值附加到数组中。虽然浏览器可能会以不同的方式实现该函数,但我高度怀疑是否需要为每次迭代计算数组的长度。

您的意思是“为什么内置函数比自定义函数慢?”不,我混淆了时间。@WillCampbell本机解决方案是用较低级别的语言编写的,因此运行速度更快。JavaScript中的代码在运行之前必须进行解析和解释。你的意思是“为什么内置函数比自定义函数慢?”不,我混淆了时间。@WillCampbell本机解决方案是用较低级别的语言编写的,因此运行得更快。JavaScript中的代码必须在运行之前进行解析和解释,所以如果每次迭代都使用-1的索引会怎么样?我还没有测试过,现在也不能,但这几乎肯定比强制的要快。我不完全确定它是否会比push快,因为它们是完全不同的动作。那么,如果我在每次迭代中使用-1的索引会怎么样?我还没有测试过,目前也不能,但这几乎肯定会比push快。我不完全确定它是否会比推送更快,因为它们是完全不同的操作。我同意答案的一般精神,但V8对
pop
push
的实现实际上是用Javascript编写的(请参阅和查找
函数ArrayPush()
)。内部JS代码显然可以访问超快的本机函数,但关键是:它不必编译得比您更快:)我同意答案的一般精神,但V8对
pop
push
的实现实际上是用Javascript编写的(请参阅和查找
function ArrayPush()
)。内部JS代码显然可以访问超快的本机函数,但关键是:它不必编译得比您更快:)