我最近开始使用更多的getter函数,而不是直接访问,以使我的代码更灵活。我很好奇这个成本在速度方面是多少。假设earth
是一个对象,我们有以下父对象:
var star={}
star.planet=earth
star.getPlanet=function(){
return this.planet
}
以下两个陈述之间的速度差异是否存在不可忽略的差异?
print(star.planet)
print(star.getPlanet())
答案 0 :(得分:13)
在V8中:
如此简短并且没有上下文分配变量的函数将被内联。除非当然已经累积了过多的内联,在这种情况下,调用仍然非常便宜,因为函数的整个执行部分适合64字节指令高速缓存行。
当您的函数使用例如arguments
而不是处于严格模式或定义引用函数变量的内部函数时,会发生上下文分配的变量。另一个问题是,如果调用者和被调用者不能共享相同的上下文,则无法内联x64函数,总而言之,避免像瘟疫那样的闭包。
请参阅:http://jsperf.com/312319sakd虽然看起来firefox使用死代码消除(这是令人沮丧的,因为浪费时间这样做?)。
Bonus:this jsperf故意让getter函数在当前的V8中不可嵌入(通过巨大的注释,这会使函数大小的启发式失败)。你可以看到,即使函数没有内联,它仍然只比直接引用道具慢25%。
请注意,当函数无法内联时,它被认为是一个黑盒子,其副作用对于调用函数是未知的,因此速度对代码具有高度上下文敏感性。
答案 1 :(得分:2)
您不需要在JavaScript中创建这样的冗余getter / setter函数。如果您在稍后阶段需要在设置属性时进行一些验证,或者在获取属性时需要进行一些准备,则可以执行此操作。
var star = {
get planet() {
this._planet.prepare()
return this._planet
},
set planet(planet) {
if (! isPlanet(planet))
throw Error('Not a planet')
this._planet = planet
}
}
star.planet = earth
...而不是改变对象的用法。