假设我们有一个类似的对象:
var foo = { a: { b: { c: { d: { e: { f: [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ] } } } } } };
我们希望在函数中使用对象的各个部分:
function doStuff() {
if ( foo.a.b.c.d.e.f[ 5 ] >= some_important_filter_value ) {
alert( "Some important filter value is " + foo.a.b.c.d.e.f[ 5 ] +
"!!\nRun for your lives!!" );
}
}
为了论证,foo
中包含的值在函数执行过程中不会发生变化,或者就此而言,根本不会发生变化。
是更好从对象中读取值并将它们存储为临时变量/常量,或完全正确使用对象foo
的完整路径作为参考价值?
即是
function doStuff() {
var mem = foo.a.b.c.d.e.f[ 5 ];
if ( mem >= some_important_filter_value ) {
alert( "Some important filter value is " + mem +
"!!\nRun for your lives!!" );
}
}
"更好" ,如果是这样,究竟是以什么方式?
谷歌Chrome浏览器控制台中的 我自己的有限测试显示100000
,同时循环深度查询对象,查询相同数量的循环查询临时变量以便大约运行同样的速度。
有效地将foo
中的值复制并存储到临时变量中以供任意次使用,在某些情况下可能具有实用价值,因为可能会降低代码/文件大小并且可读性 有所改进,但为了这个问题的目的而将其放在一边,还可以提出其他有利于哪些论点?
对于现代JS解释器来说,创建和处理临时变量对于简单地直接引用对象中的值来说无疑是微不足道的?
var temp = foo.a.b.c...
为什么以及如何更好而不是跳过定义并仅使用我们已有的参考值?
我认为从根本上说,我要问的是 - 我的参考中有多少点真的很重要,因为从长远来看,它只是一个参考 - 或者是它?
答案 0 :(得分:1)
正如您自己测试的那样,并且如上面的Matt Burland所证实的,嵌套对象引用在性能上与复制引用没有显着差异。
您希望在性能方面注意的是函数调用。如果你有foo.a()。b()。c()...而是函数调用自己开始变得昂贵。在这里,差异变得明显,如我对Matt的jsperf测试的小修订版所示:http://jsperf.com/temp-vs-dot/2
答案 1 :(得分:1)
在精湛的迂腐境界中,你将一次又一次地支付解决这些参考资料的惩罚。
如果这些是“类”(构造对象,可能引用 proto 链上的值),那么您需要支付额外的代价,即无法在对象上找到值,并提升 proto 链直到你做(或者点击Object.prototype,仍然会错过该属性,并在尝试访问该缺失对象的属性时抛出引用错误。)
现在,总而言之,如果在现代发动机的压力测试中增加了1毫秒,我会大吃一惊。
Chrome的V8将在很长一段时间内重新编译代码,其中包括展开循环,内联函数等等。只要你每次都使用一致的函数(传递类似的参数/参数类型)。
关于在Chrome中编写游戏引擎的相关内容有一些很好的讨论,大约在2012年。我相信。道德观点是,如果做了多次,你所做的大部分工作都会被编译成内联操作......
...在新的浏览器中......
当您执行类似
之类的操作时,您会受到性能影响if (i % 3001) { a.b.e.f.g[6]; }
else { a.b.c.d.e.f[5]; }
再次,那是现代引擎。
如果您在2003 Windows XP系统上运行IE6运行负载测试,由于上述原因,您的数字应该不同。
它们不应该是几百毫秒... ... 但是,它们应该多次反映解除引用值的性能损失,如果属性原型链接,性能损失应该增加,并且根据链上的距离再次增加以解析每个属性。
也就是说,我指的是a.b.c
与a["b"]["c"]
的测试明显不同的浏览器。