题主来了
先上结论:缓存 Array.lengh 对优化影响不大,甚至会减慢。
1、从测试结果上看
stackoverflow 上也有这个讨论,
For-loop performance: storing array length in a variable。
accepted 的答案是说缓存会起到加速的结果,给出了
jsPerf测试。
但是有答案反对,也给出了
jsPerf测试。
两个答案的区别在于 (
Loop-invariant code motion) 后面会讲到。
从另一篇文章
Shoud I have to cache my array’s length?的测试结果也可以看出缓存差别不大。
还有这篇
JavaScript's .length Property is a Stored Value2、从 V8 的中间代码分析
这篇文章
http:// mrale.ph/blog/2014/12/2 4/array-length-caching.html从 V8 的 hydrogen 探讨 Array.length 在 for 循环中的处理。
正如上面提到的
Loop-invariant code motion,引擎会把能确定不变的代码移到循环外。
所以像下面这种代码也不会影响引擎对 Array.length 的优化:
function uncached(arr) { for (var i = 0; i < arr.length; i++) { arr[i] } }
而当循环中调用不可
内联函数时,引擎没法做优化,每次循环都会重新计算一遍 length
function BLACKHOLE(sum, arr) { try { } catch (e) { } } function uncached(arr) { var sum = 0; for (var i = 0; i < arr.length; i++) { sum += arr[i]; if (sum < 0) BLACKHOLE(arr, sum); } return sum; }
但这时即便是在循环外缓存了 length 也是没有用的,引擎没法预判数组的变化,当需要访问数组元素时会触发 bounds check ,从而照样要计算一遍 length 。所以缓存 length 是没有用的。
甚至,由于多了一个变量,底层的寄存器分配器每次循环还要多一次恢复这个变量。当然这个只有在大规模的情况下才会看出区别。
当然这篇文章也有局限性,仅仅讨论了 V8 引擎,也没有讨论访问 length 代价更高的 HTMLCollection 。但这已经足够让我们不用再局限于缓存的写法,可以放开来按照自己喜欢的方式去写循环了。
【完】