读取数组的`length`属性真的在JavaScript中花费那么大的代价吗?

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


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


// vs


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

但是,我认为也许length只有在创建和更改数组时才更新该属性。因此,与读取存储在变量中的操作相比,读取它的操作不会太昂贵(与其他语言的其他方法相对,后者可能需要在内存中寻找内容的结尾,例如strlen()在C语言中)。


我有两个问题。我也对它的工作方式感兴趣,所以请不要用过早的优化工具打我。


假设浏览器中的JavaScript引擎。


length在JavaScript中缓存数组的属性有什么好处吗?在读取对象属性的局部变量时还有更多的事情吗?

该length属性是否仅在创建时以及在on shift()和pop()type方法上进行了更改,这些方法不返回新数组,否则仅存储为整数?


智慧大石
浏览 474回答 3
3回答

饮歌长啸

据我所知,似乎数组的长度是在内部缓存的(至少在V8中)。(详细信息?请继续阅读:))因此,这个问题在我的脑海中浮现了好几次,我已经决定找出问题的根源(至少在一个实现中)。挖掘V8源代码会产生JSArray类。// The JSArray describes JavaScript Arrays//&nbsp; Such an array can be in one of two modes://&nbsp; &nbsp; - fast, backing storage is a FixedArray and length <= elements.length();//&nbsp; &nbsp; &nbsp; &nbsp;Please note: push and pop can be used to grow and shrink the array.//&nbsp; &nbsp; - slow, backing storage is a HashTable with numbers as keys.我假设数组元素的类型决定了它是快还是慢。我到了set_has_fast_elements(set_bit_field2(bit_field2() | (1 << kHasFastElements)))中设置了一个位标志,这是我在Google代码中查找时要绘制挖掘线的地方,而本地没有源代码。现在,它似乎是任何时候任何操作是在阵列上完成(这是一个子类的JSObject,就会调用作出NormalizeElements(),其执行以下操作:// Compute the effective length.&nbsp; int length = IsJSArray() ?&nbsp; &nbsp; &nbsp; Smi::cast(JSArray::cast(this)->length())->value() :&nbsp; &nbsp; &nbsp; array->length();因此,在回答您的问题时:Chrome(或其他使用V8的浏览器)在缓存length数组的属性方面似乎没有任何优势(除非您做一些奇怪的事情将其强制为slow(我不确定这些条件是什么) )-话虽如此,我很可能会继续缓存,length直到有机会浏览所有 OS浏览器的实现;)在对象上执行任何操作length后,该属性似乎已更改。编辑:附带说明,似乎“空”数组实际上已分配为具有4个元素:// Number of element slots to pre-allocate for an empty array.static const int kPreallocatedArrayElements = 4;我不知道数组有多少元素增长由曾经的范围已经超出了-我没有挖的是深:)

慕妹3242003

本文通过询问IRHydra生成的代码来研究V8和Chrome中的自动缓存:Grinch如何通过Vyacheslav Egorov 窃取array.length他发现在某些条件下,手动缓存.length实际上增加的开销而不是提高性能!但是无论如何,这种微优化不可能为您的用户带来任何明显的收益。为了他们和您的利益,请专注于易于阅读的代码,并在代码中使用良好的数据结构和算法!避免过早的优化:关注优美的代码,直到出现性能问题。只有这样,才能通过性能分析找出瓶颈,然后仅对代码的那部分进行优化。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript