为什么我的原型这么慢?
Why are my prototypes so slow?
好的,所以我写了这个简单的 javascript 函数来使我的代码更具可读性:
Number.prototype.isBetween=function(a,b){
return(this>=a&&this<b);
};
结果证明这很慢:我尝试了这个 "benchmark"(我真的不知道如何正确地做这些事情,但这无论如何都证明了我的观点):
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 只是一个非常糟糕的主意吗?这是怎么回事?
原因是要应用方法isBetween
,需要将主体k转换为Number
客体。这称为拳击 或primitive wrapping。
然后应用 isBetween
方法,其中比较运算符 >
需要从 this
对象中检索原始值,...两次。
这是附加函数调用(涉及堆栈)之上的所有附加开销。
这个总开销比需要进行的实际比较要多,因此对性能的影响相对较大。
严格模式
正如@Bergi 在下面的评论中提到的,above-described 包装 does not happen in strict mode MDN :
the value passed as this
to a function in strict mode is not forced into being an object (a.k.a. "boxed"). [...] automatic boxing [is] a performance cost [...] Thus for a strict mode function, the specified this
is not boxed into an object.
你会发现当切换到严格模式时,增加的性能成本会消失:
"use strict";
好的,所以我写了这个简单的 javascript 函数来使我的代码更具可读性:
Number.prototype.isBetween=function(a,b){
return(this>=a&&this<b);
};
结果证明这很慢:我尝试了这个 "benchmark"(我真的不知道如何正确地做这些事情,但这无论如何都证明了我的观点):
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 只是一个非常糟糕的主意吗?这是怎么回事?
原因是要应用方法isBetween
,需要将主体k转换为Number
客体。这称为拳击 或primitive wrapping。
然后应用 isBetween
方法,其中比较运算符 >
需要从 this
对象中检索原始值,...两次。
这是附加函数调用(涉及堆栈)之上的所有附加开销。
这个总开销比需要进行的实际比较要多,因此对性能的影响相对较大。
严格模式
正如@Bergi 在下面的评论中提到的,above-described 包装 does not happen in strict mode MDN :
the value passed as
this
to a function in strict mode is not forced into being an object (a.k.a. "boxed"). [...] automatic boxing [is] a performance cost [...] Thus for a strict mode function, the specifiedthis
is not boxed into an object.
你会发现当切换到严格模式时,增加的性能成本会消失:
"use strict";