我正在为极其资源受限的嵌入式设备(http://www.espruino.com)编写一个JavaScript解释器,每当我认为我已经正确实现了一些JavaScript时,我就意识到我错了。
我现在的问题是关于[]
。您如何正确实现JavaScript最基本的部分之一?
我查看了JavaScript规范,也许我找不到正确的位,但我找不到有用的答案。
我之前曾假设您实际上有两个'地图' - 一个用于整数,一个用于字符串。并且数组长度是最高整数加1的值。然而,这似乎是错误的,根据铬的jsconsole:
var a = [];
a[5] = 42;
a["5"]; // 42
a.length; // 6
但也是:
var a = [];
a["5"] = 42;
a[5]; // 42
a.length; // 6
所以......很棒 - 一切都被转换成一个字符串,并且使用表示整数的最高值字符串(加一)来获取长度?错。
var a = [];
a["05"] = 42;
a.length; // 0
"05"
是一个有效的整数 - 即使在八进制中也是如此。那为什么它不影响长度?
你是否必须将字符串转换为整数,然后在转换回字符串时检查它是否匹配?
有没有人引用用于存储和获取数组或对象中项目的确切算法?它看起来应该很简单,但看起来它实际上并非如此!
答案 0 :(得分:4)
请参阅MDN
也可以引用JavaScript数组索引(例如, 年[[2“]而不是年[2]),虽然没有必要。 2英寸 年[2]最终被JavaScript强制转换为字符串 无论如何,通过隐式toString转换引擎。那是为了 这个原因,“2”和“02”指的是两个不同的插槽 years对象和以下示例记录为true:
console.log(years["2"] != years["02"]);
因此,使用a["5"]
访问数组时,a["05"]
会在数组对象上设置属性。
答案 1 :(得分:4)
正如规范所说,并被其他人注意到:
“当且仅当ToString(ToUint32(P))等于P且ToUint32(P)不等于2 ^ 32-1时,属性名称P(以String值的形式)是一个数组索引。“
这就解释了为什么在您的方案中"5"
被视为数组索引而"05"
不是:
console.log("5" === String("5" >>> 0));
// true, "5" is equal to "5", so it's an index
console.log("05" === String("05" >>> 0));
// false, "05" is not equal to "5", so it's not an index
注意:Zero-fill right shift是JS中替换ToUint32
的最短路径,将数字移动为零。
答案 2 :(得分:3)
数组只是对象。这意味着它们可以具有不被视为数组元素的其他属性。
如果方括号参数是整数,则使用它来执行对数组的赋值。否则,它将其视为字符串并将其作为属性存储在数组对象上。
根据delnan的评论和DCoder的评论进行编辑,这就是JavaScript如何确定它是否是数组的适当索引(而不仅仅是属性): http://www.ecma-international.org/ecma-262/5.1/#sec-15.4
答案 3 :(得分:1)
数组也是对象。
通过这样做
a["05"] = 5;
你正在做同样的事情:
a.05 = 5;
但是,以上操作会导致语法错误,因为在点无法以数字开头后指定的属性。
所以,如果你这样做:
a = [];
a["05"] = 5;
您仍然有空数组,但名为a
的{{1}}的属性值为05
。
数字5
is an array index当且仅当x
等于ToString(ToUint32(x))
时(如果x
不符合要求,则为<}}。< / p>