首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >在JavaScript中读取数组的`length`属性真的是一个开销很大的操作吗?

在JavaScript中读取数组的`length`属性真的是一个开销很大的操作吗?
EN

Stack Overflow用户
提问于 2011-04-22 14:36:04
回答 5查看 14.4K关注 0票数 71

我一直认为在JavaScript中缓存数组的长度是一个好主意(特别是在for循环的情况下),因为计算数组长度的开销很大。

示例

代码语言:javascript
复制
for (var i = 0; i < arr.length; i++) { }

// vs

for (var i = 0, arrLength = arr.length; i < arrLength; i++) { }

但是,我认为length属性可能只在数组创建和更改时更新。因此,与读取存储在变量中的它相比,读取它不应该是一个代价太高的操作(与其他语言中的其他方法相反,其他语言中的其他方法可能需要在内存中查找某些内容的结尾,例如C中的strlen() )。

我有两个问题。我也对它是如何工作的很感兴趣,所以请不要用过早的优化棒来打击我。

假设浏览器中的JavaScript引擎。

  1. 在JavaScript中缓存数组的length属性有什么好处吗?在对象的属性上读取局部变量是否涉及更多内容?
  2. 是不是只在创建时以及在不返回新数组的shift()pop()类型方法上更改了length属性,否则只是将其存储为整数?
EN

回答 5

Stack Overflow用户

发布于 2011-04-22 15:52:52

TL;DR:

据我所知,数组的长度似乎是在内部缓存的(至少在V8中)。

(详细信息?继续阅读:)

因此,这个问题在我的脑海中徘徊了几次,我决定找出问题的根源(至少在一个实现中)。

研究一下V8源代码,就得到了JSArray类。

代码语言:javascript
复制
// 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(),它执行以下操作:

代码语言:javascript
复制
// Compute the effective length.
  int length = IsJSArray() ?
      Smi::cast(JSArray::cast(this)->length())->value() :
      array->length();

所以,在回答你的问题时:

  1. 在Chrome (或其他使用V8的浏览器)中,缓存数组的length属性似乎没有任何优势(除非您做了一些奇怪的事情,强制它为slow (我不确定这些条件是什么)-话虽如此,我很可能会继续缓存length,直到我有机会了解所有OS浏览器实现;)
  2. 在对对象执行任何操作后,length属性似乎都会更改。

<代码>G220

编辑:

顺便说一句,似乎一个“空”数组实际上被分配了4个元素:

代码语言:javascript
复制
// Number of element slots to pre-allocate for an empty array.
static const int kPreallocatedArrayElements = 4;

我不确定一旦超出界限,数组会增加多少元素--我没有深入挖掘:)

票数 28
EN

Stack Overflow用户

发布于 2011-04-22 15:06:38

另一组performance tests。循环是在一个包含百万个随机数的数组上进行的,其中包含一个空循环。

在Chrome中,具有缓存和非缓存长度的循环的时钟几乎相同,所以我猜测这是一个缓存长度的V8优化。

在Safari和Firefox中,缓存长度始终比非缓存版本快2倍左右。

票数 13
EN

Stack Overflow用户

发布于 2014-12-29 23:56:05

本文通过向IRHydra请求生成的代码,研究了V8和Chrome中的自动缓存:

How the Grinch stole array.length access”,作者: Vyacheslav Egorov

他发现,在某些情况下,手动缓存.length实际上增加了开销,而不是提高性能!

但不管怎样,这种微优化不太可能为用户带来任何明显的收益。为了他们的利益,也为了你的利益,专注于清晰易读的代码,并在你的代码中使用好的数据结构和算法!

Avoid premature optimisation:专注于优雅的代码,直到出现性能问题。只有这样,才能通过分析找出瓶颈,然后只优化那部分代码。

票数 8
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5752906

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档