2014-10-20 36 views
2

假设我们有一个对象是这样的:使用临时变量代替重复的完整引用会更好吗?

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!!"); 
    } 
} 

“更好”,如果是这样,在什么方式(S)?在谷歌C​​hrome浏览器的JS控制台

我自己有限的测试显示100000 while循环深深查询对象,对相同数量的循环查询一个临时变量在运行大致相同的速度的。

有效复制和存储从foo一个值使用的临时变量任意次数,可以在某些情况下具有实用价值,只要该代码/文件大小可以被减少和可读性可以是改善,但在离开除了这个问题之外,还有什么其他有利于我们的论据?

对于现代JS解释器来说,临时变量的创建和处理肯定不会轻而易举,而不是直接引用对象内的值?

为什么,以及如何将var temp = foo.a.b.c...比跳绳的定义,只是通过我们已经有了参考使用值更好

我想基本上我问的是 - 在我的参考文献中有多少点是真的,因为从长远来看,这只是一个参考 - 或者它是什么?

+2

*“在我的参考文献中有多少点是真的,因为从长远来看,这只是一个参考”*不。在某种程度上,一种方式会比另一种更“*高效”*,但最终执行的差异将会非常小,以至于无关紧要。 – 2014-10-20 20:35:51

+2

看起来像可读性和代码维护是另一个因素 – charlietfl 2014-10-20 20:36:05

+1

我不会担心它,直到你分析你的代码并发现它是一个瓶颈。另一方面,可读性是一个更大的问题,因此,将'foo.a.b.c ...'复制到一个临时变量中可能是一个好主意,当你要多次引用它时。这也使得在下次意外错误输入和访问'foo.a.b.c'和'foo.a.c.b'更困难。 – 2014-10-20 20:39:47

回答

1

在美妙的职业领域,你要付出一次又一次解决这些引用的惩罚。

如果这些“类”(构造的对象,这可能是在链参考值),那么你付出没有找对象的价值,并提升了链的附加处罚直到你这样做(或者当你尝试访问那个缺少的对象的属性时,仍然会错过这个属性,并且抛出一个引用错误)(或者点击Object.prototype)。现在,所有人都告诉我,如果在现代发动机的压力测试中增加了1ms,那么我会大吃一惊。 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系统上运行负载测试,则由于上述原因,您的数字应该不同。

他们不应该数百毫秒关的...
他们应该,但反映多次提领值的性能损失,如果属性挂钩,业绩点球应该增加,并且增加再次基于距离链上的距离来解决每个属性。

也就是说,我指的是浏览器,其中a.b.ca["b"]["c"]的测试可察觉地不同。

+0

这可以归结为“错误伤害更多......”,但错误总是受到伤害,是的,现代编译器/口译员的效率让我首先提出这个问题。如果这是最早的时候,我毫不怀疑地方/临时变量是“理想的”,但现在是未来,各处的一次性变量虚拟似乎是完全没有必要的。我仍然怀疑是否有更多的东西比满足眼睛。 – 2014-10-20 21:40:39

+0

@FredGandt:优化开销的编译器不是编写错误代码的借口。在这种特殊情况下,重复访问属性并不是干的。 – Bergi 2014-10-20 21:42:38

+1

@FredGandt如果你再读一遍,你应该注意,它不是一个“错误”,而是语言的一个特征,用来爬上__proto__链。而且,这不是在编译代码时跳出“错误”的问题;传递数字,传递数字的字符串表示形式,或传递特定类型的对象实例,然后传入不同类型的实例,或者传递一个实例,其中属性已添加或从构造函数都可以引发一个操作。现在,这些解除操作比解除引用具有更大的影响。 – Norguard 2014-10-20 21:48:12

1

正如你自己测试过的,并且如上面Matt Burland所确认的那样,嵌套对象引用在性能上与复制引用没有多大差别。

你想要在性能方面观察的是函数调用。如果你有foo.a().b().c()...相反,函数调用自己开始变得昂贵。这里的差别就变得很明显了,正如我对Matt的jsperf测试的小修改所显示的那样:http://jsperf.com/temp-vs-dot/2

+0

好点。我必须承认,我预计在性能上会有比我看到的更大的差异。但是,即使小的性能问题在某些情况下也很重要。绝对值得记住。 – 2014-10-20 22:20:03