【发布时间】:2012-03-03 06:40:59
【问题描述】:
JavaScript Array 和 Object 之间的区别不是很大。其实Array好像主要是增加了length这个字段,所以Arrays和Objects都可以作为数值数组使用:
var ar = new Array();
ar[0] = "foo";
ar["bar"] = "foo";
var ob = new Object();
ob[0] = "foo";
ob["bar"] = "foo";
assert(ar[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar); // Should be true.
所以我的问题是,在流行的 JavaScript 引擎中(V8、JavaScriptCore、SpiderMonkey 等),这是如何处理的?显然,我们不希望我们的数组实际存储为带有键值的哈希映射!我们如何合理地确定我们的数据存储为一个实际的数组?
据我所知,引擎可以采取几种方法:
-
Array的实现方式与Object完全相同 - 作为带有字符串键的关联数组。 -
Array是一种特殊情况,有一个类似std::vector的数组支持数字键,如果你这样做ar[100000000] = 0;,还有一些密度启发式以防止疯狂的内存使用 -
Array与Object相同,所有对象都会得到启发,看看使用数组是否更有意义。 - 我没有想到的极其复杂的事情。
如果有适当的数组类型,这真的会更简单(咳嗽WebGL类型化数组咳嗽)。
【问题讨论】:
-
这个article有点老了,没有明确解释实现。但是,它会进行详细的性能测量,并推断可能的实现。
-
数组不是只是一个带有
length属性的地图。如果是,那么移位或取消移位会破坏索引(即,将一个值移出数组,它仍然从索引 0 开始,而不是 1)。所以至少还有一些事情要做。 (当然,这并不一定说明实施的任何内容) -
您为什么认为
r[0] == ob[0] == ar["0"] == ob["0"] == ar.bar == ob.bar是真的?'a' == 'a' == 'a'为 false,因为它的计算结果为true == 'a',而false的计算结果为。 -
@Flambino,这不是真的。
shift是作为通用方法实现的,而不是特定于数组的。它适用于常规对象。移位之所以有效,是因为它获取第一个值,然后循环分配给左的所有值,最后删除最后一个元素并设置长度。 -
@Flambino,尝试运行
var a = { 0: 0, 1: 1, length: 2 }; Array.prototype.shift.apply(a); alert(JSON.stringify(a))。你应该可靠地得到{"0":1,"length":1}。
标签: javascript arrays performance v8 spidermonkey