首先,这有何难度或可读性不佳之处?
var i = someArray.length;
while(i--){
}
这不是什么奇怪的微优化,只是一种基本的工作避免原则。尽量不多次使用'.'或'[]'运算符应该像不重复计算π一样显而易见(假设你不知道我们已经在Math对象中有了它)。
如果someArray完全内部于函数,则其长度属性可以进行JIT优化,这实际上类似于一个getter,每次访问时都会计算数组的元素数量。JIT可以看到它完全在局部作用域中,并跳过实际的计数行为。
但这涉及到相当复杂的问题。每次对修改数组的任何操作,都必须将长度视为静态属性,并告诉您的数组修改方法(我指的是本机代码方面)手动设置该属性,而通常长度只是每次查询时都会计算项数。这意味着每次添加新的数组修改方法时,您都必须更新JIT以使局部作用域数组的长度引用分支行为。
我可以看到Chrome最终会做到这一点,但根据一些非常非正式的测试,我认为它还没有做到。我不确定IE是否会将此级别的性能微调作为重点。至于其他浏览器,您可以强烈主张维护问题,即必须为每个新数组方法分支行为,这比其价值更麻烦。至少,它不会得到高优先级。
最终,在典型的JS循环中,即使在旧浏览器中,每个循环周期访问长度属性也不会花费太多成本。但我建议养成缓存任何被执行超过一次的属性查找的习惯,因为对于getter属性,您永远无法确定正在做多少工作,哪些浏览器以什么方式进行了优化或者在将someArray移动到函数之外时可能遇到的性能成本,这可能导致每次执行该属性访问时,调用对象都要检查十几个地方才能找到它正在寻找的内容。
缓存属性查找和方法返回很容易,可以清除代码,并在修改面前使其更加灵活和性能稳健。即使有一两个JIT在涉及多个“if”的情况下使其无关紧要,您也不能确定它们总是会这样做,或者您的代码是否会继续使其成为可能。
因此,是的,抱歉反对让编译器处理的言论,但我不明白为什么您不想缓存属性。它很容易,它很简洁,它保证了更好的性能,而不管浏览器或对象的移动其属性被检查到外部作用域。
但是我真的很生气,因为现在Word文档的加载速度和1995年一样慢,而且人们继续编写可怕的低性能Java网站,尽管Java的VM据说在性能方面打败了所有非编译竞争者。我认为这种让编译器处理性能细节并且“现代计算机速度非常快”的观念与此有很大关系。在易于避免且不威胁可读性/可维护性的情况下,我们应该始终谨记避免工作,以我的看法。从长远来看,改变做事方式从未帮助我(或我怀疑任何人)更快地编写代码。