我一直认为在JavaScript中缓存数组的长度是一个好主意(特别是在for
循环的情况下),因为计算数组长度的开销很大。
示例
for (var i = 0; i < arr.length; i++) { }
// vs
for (var i = 0, arrLength = arr.length; i < arrLength; i++) { }
但是,我认为length
属性可能只在数组创建和更改时更新。因此,与读取存储在变量中的它相比,读取它不应该是一个代价太高的操作(与其他语言中的其他方法相反,其他语言中的其他方法可能需要在内存中查找某些内容的结尾,例如C中的strlen()
)。
我有两个问题。我也对它是如何工作的很感兴趣,所以请不要用过早的优化棒来打击我。
假设浏览器中的JavaScript引擎。
length
属性有什么好处吗?在对象的属性上读取局部变量是否涉及更多内容?shift()
和pop()
类型方法上更改了length
属性,否则只是将其存储为整数?发布于 2011-04-22 15:52:52
TL;DR:
据我所知,数组的长度似乎是在内部缓存的(至少在V8中)。
(详细信息?继续阅读:)
因此,这个问题在我的脑海中徘徊了几次,我决定找出问题的根源(至少在一个实现中)。
研究一下V8源代码,就得到了JSArray类。
// The JSArray describes JavaScript Arrays
// Such an array can be in one of two modes:
// - fast, backing storage is a FixedArray and length <= elements.length();
// Please note: push and pop can be used to grow and shrink the array.
// - slow, backing storage is a HashTable with numbers as keys.
我假设数组元素的类型决定了它是快还是慢。我在set_has_fast_elements
(set_bit_field2(bit_field2() | (1 << kHasFastElements))
)中设置了一个位标志,这是我在谷歌代码中查找时发现的地方,因为我在本地没有源代码。
现在,看起来any time any操作是在数组上完成的(这是JSObject
的子类,调用NormalizeElements()
,它执行以下操作:
// Compute the effective length.
int length = IsJSArray() ?
Smi::cast(JSArray::cast(this)->length())->value() :
array->length();
所以,在回答你的问题时:
length
属性似乎没有任何优势(除非您做了一些奇怪的事情,强制它为slow
(我不确定这些条件是什么)-话虽如此,我很可能会继续缓存length
,直到我有机会了解所有OS浏览器实现;)length
属性似乎都会更改。<代码>G220
编辑:
顺便说一句,似乎一个“空”数组实际上被分配了4个元素:
// Number of element slots to pre-allocate for an empty array.
static const int kPreallocatedArrayElements = 4;
我不确定一旦超出界限,数组会增加多少元素--我没有深入挖掘:)
发布于 2011-04-22 15:06:38
发布于 2014-12-29 23:56:05
本文通过向IRHydra请求生成的代码,研究了V8和Chrome中的自动缓存:
“
How the Grinch stole array.length access”,作者: Vyacheslav Egorov
他发现,在某些情况下,手动缓存.length
实际上增加了开销,而不是提高性能!
但不管怎样,这种微优化不太可能为用户带来任何明显的收益。为了他们的利益,也为了你的利益,专注于清晰易读的代码,并在你的代码中使用好的数据结构和算法!
Avoid premature optimisation:专注于优雅的代码,直到出现性能问题。只有这样,才能通过分析找出瓶颈,然后只优化那部分代码。
https://stackoverflow.com/questions/5752906
复制相似问题