javascript Array
和Object
之间的差异不是很大。事实上似乎Array
主要添加了length
字段,因此您可以同时使用Array
和Object
作为数字数组:
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
相同,并且所有对象都会获得启发式功能,以查看使用数组是否更有意义。如果有适当的数组类型( cough WebGL类型数组 cough ),这会更简单。
答案 0 :(得分:13)
在SpiderMonkey中,数组基本上是作为jsvals的C数组实现的。这些被称为“密集阵列”。但是,如果你开始对它们做类似非数组的事情 - 比如像对象一样对待它们 - 它们的实现会变成非常类似于对象的东西。
故事的道德:当你想要一个数组时,使用一个数组。如果需要对象,请使用对象。
哦,jsval是一种可变参数类型,可以表示64位C类型中任何可能的JavaScript值。
答案 1 :(得分:7)
在V8和Carakan(可能是Chakra)中,具有名称为数组索引(在ES5中定义)的属性的所有(非主机)对象(包括数组和非数组)都存储为密集数组(包含一些值包装器的C数组)或稀疏数组(实现为二叉搜索树)。
统一对象表示显示它影响枚举顺序:对象,SpiderMonkey和SquirrelFish都按插入顺序给出所有属性;并且使用数组,它们通常(至少在SM中有特殊情况!)数组索引首先是插入顺序中的所有其他属性。无论对象类型如何,V8,Carakan和Chakra总是以插入顺序首先给出数组索引,然后是所有其他属性。