【问题标题】:Why are my prototypes so slow?为什么我的原型这么慢?
【发布时间】:2017-02-04 12:11:55
【问题描述】:

好的,所以我编写了这个简单的 javascript 函数以使我的代码更具可读性:

Number.prototype.isBetween=function(a,b){
    return(this>=a&&this<b);
};

现在这变得非常缓慢:我尝试了这个“基准”(我真的不知道如何正确地做这些事情,但这证明了我的观点):

var res=0;
var k=20;
var t=new Date().getTime();
for(var i=0;i<10000000;i++){if(k.isBetween(13,31)){res++;}}
console.log(new Date().getTime()-t);

var res=0;
var k=20;
var t=new Date().getTime();
for(var i=0;i<10000000;i++){if(k>=13&&k<31)){res++;}}
console.log(new Date().getTime()-t);

第一个脚本在 chrome 中大约需要 3000 毫秒(我正在使用并且我感兴趣的是 chrome),而第二个脚本只需要 24 毫秒 - 整整 125 毫秒 .扩展现有类 javascript 是否提供了一个非常糟糕的主意?这是怎么回事?

【问题讨论】:

标签: javascript prototype benchmarking


【解决方案1】:

原因是要应用isBetween 方法,需要将主题k 转换为Number 对象。这称为 boxingprimitive wrapping

然后应用isBetween 方法,比较运算符&gt; 需要从this 对象中检索原始值,... 两次。

这是附加函数调用(涉及堆栈)之上的所有额外开销。

这个总开销比实际需要进行的比较要多,因此对性能的影响比较大。

严格模式

正如@Bergi 在下面的cmets 中提到的,上述包装does not happen in strict mode MDN

作为this 传递给严格模式中的函数的值不会被强制为对象(也称为“装箱”)。 [...] 自动装箱 [是] 性能成本 [...] 因此,对于严格模式功能,指定的 this 不会装箱到对象中。

您会发现,当切换到严格模式时,额外的性能成本会消失:

"use strict";

【讨论】:

  • 为什么k需要转成数字?设置k=20不是已经是数字了吗?
  • typeof k 仍然是“数字”。它需要转换为对象。
  • 原始数字和数字对象之间存在差异。原始值没有方法,因此它会即时转换为对象。
  • 另外,第二个更快的原因是在这里您只需使用数字和运算符就可以进行原始数据类型的所有计算。
  • 看起来几乎都是对象转换的原因。我做了一个 jsperf jsperf.com/number-method-vs-function 和一个常规函数的性能几乎与内联比较相同,但该方法慢了 200 倍。
猜你喜欢
  • 1970-01-01
  • 2023-03-28
  • 2012-10-17
  • 2021-10-20
  • 1970-01-01
  • 2021-09-03
  • 2011-03-07
相关资源
最近更新 更多