Javascript 使用临时变量代替重复的完整引用是否更好?
假设我们有一个类似于:Javascript 使用临时变量代替重复的完整引用是否更好?,javascript,performance,object,Javascript,Performance,Object,假设我们有一个类似于: 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
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
作为值的参考?
i、 e.是
“更好”,如果是,具体以什么方式
我自己在Google Chrome的JS控制台上进行的有限测试显示100000
在深入查询对象时,与查询临时变量以大致相同速度运行的相同数量的循环相比
有效地将foo
中的值复制并存储到临时变量中以供多次使用,在某些情况下可能具有实用价值,因为代码/文件大小可能会减小,可读性可能会提高,但出于本问题的目的,请将其放在一边,还有哪些支持它的论点
对于现代JS解释器来说,创建和处理临时变量肯定比直接引用对象中的值要简单得多
为什么以及如何将var temp=foo.a.b.c.
优于跳过定义,仅通过我们已有的引用使用值?
我想基本上我要问的是-我的引用中有多少点真的很重要吗,因为从长远来看,它只是一个引用-或者是吗?正如您自己测试的那样,正如上面Matt Burland所确认的,嵌套对象引用在性能上与复制的引用没有明显的不同
在性能方面,您需要注意的是函数调用。如果您有foo.a().b().c()。。。相反,函数调用本身开始变得昂贵。在这里,差异变得明显,正如我对Matt的jsperf测试所做的小修改所示:在学究式的奇妙领域中,你将一次又一次地为解决这些引用而付出代价 如果这些是“类”(构造的对象,它可能引用proto链上的值),那么您需要支付额外的惩罚,即无法在对象上找到值,并将proto链升序,直到找到为止(或单击Object.prototype,当您尝试访问缺少的对象的属性时,仍会丢失该属性,并引发引用错误) 总而言之,如果你的现代发动机压力测试增加了1毫秒,我会大吃一惊 Chrome的V8将在动态重新编译代码方面发挥很大作用,其中包括展开循环、内联函数等;只要每次都一致地使用函数(传递类似的参数/参数类型) 我相信,大约在2012年左右,关于用Chrome编写游戏引擎,有一些很好的讨论 寓意是,如果你做了几次以上,你所做的大部分事情都会被编译成一个内联操作 …在新浏览器中 当你做了这样的事情时,你会受到表演上的打击
if (i % 3001) { a.b.e.f.g[6]; }
else { a.b.c.d.e.f[5]; }
…同样,这是现代发动机
如果您要在运行IE6的2003 Windows XP系统上运行负载测试,由于上述原因,您的数字应该不同
它们不应该有几百毫秒的间隔…但是,它们应该多次反映解引用值的性能影响,如果属性链接到proto,则性能损失应该增加,并根据链上的距离再次增加,以解析每个属性
换句话说,我指的是那些浏览器,
a.b.c
与a[“b”][“c”]
的测试在视觉上是不同的。“我的参考中有多少个点真的很重要吗,因为从长远来看,这只是一个参考”不。在某种程度上,一种方法会更“有效”相比于另一个,但最终在执行上的差异将是如此之小,以至于与此无关。看起来可读性和代码维护是另一个因素,除非您分析代码并发现它是一个瓶颈,否则我不会担心它。另一方面,可读性是一个更大的问题,因此复制foo。a、 b.c.
当您要多次引用临时变量时,将其放入临时变量可能是一个好主意。这也会使您更难一次意外地键入和访问foo.a.b.c
以及下一次访问foo.a.c.b
。“我自己的有限测试”:如果你好奇的话,你也可以试试。这是我设置的一个测试:,几乎没有区别。这可以归结为“错误伤害更大…”,但错误总是有害的,是的,正是现代编译器/解释器的效率让我首先提出了这个问题。如果这是二十世纪初,我将毫不怀疑局部/临时变量是“理想的”,但它现在是未来,到处都有大量的一次性变量似乎完全没有必要。我继续怀疑它是否有比看上去更多的地方。@FredGandt:编译器优化了您的开销,这不是编写糟糕代码的借口。在这种特殊情况下,重复长时间的属性访问不是干巴巴的。@FredGandt如果您阅读它的话。@FredGandt当然,你应该注意到,爬上原型链不是一个“错误”,而是语言的一个特性。此外,这不是一个在编译代码中犯“错误”的问题;传递一个数字,而不是传递一个数字的字符串表示,或者传递一个特定类型的对象实例,然后传入一个in
if (i % 3001) { a.b.e.f.g[6]; }
else { a.b.c.d.e.f[5]; }