2013-04-11 79 views
12

我正在为非常资源有限的嵌入式设备(http://www.espruino.com)编写JavaScript解释器,每当我认为我已经正确实现了一些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"是一个有效的整数 - 即使在八进制。那为什么它不影响长度?

您是否必须将字符串转换为整数,然后检查转换回字符串时是否匹配?

是否有人提及用于存储和获取数组或对象中的项目的确切算法?它看起来应该很简单,但它看起来实际上不是!

+6

【标准】(http://www.ecma-international.org/ecma-262/5.1/#sec-15.4)说:“*属性名称'P'(形式为'String'值)是当且仅当'ToString(ToUint32(P))'等于'P'且'ToUint32(P)'不等于'2 ** 32-1'。*“的数组索引。 – DCoder 2013-04-11 19:29:42

+6

如果您正在撰写口译员,则不应使用假设。你应该阅读规范。 – 2013-04-11 19:45:54

+0

为什么不使用现有的,功能强大且符合标准的JS实现,比如V8?我在http://www.espruino.com/Performance上读到的东西听起来很可怕: -/ – Bergi 2013-04-11 20:11:51

回答

4

作为规格说,并且被别人注意的是:

“属性名称P(在一个字符串值的形式)是一个数组索引当且仅当的ToString(ToUint32(P))等于P,ToUint32(P)不等于2^32-1。“

这解释了为什么在方案"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的替代品,移位数通过零。

+0

谢谢 - 这也解释了数组长度的问题,其他答案没有真正解决。感谢链接到规格以及DCoder – 2013-04-12 20:47:16

3

数组只是对象。这意味着它们可以具有不属于数组元素的其他属性。

如果方括号参数是一个整数,它使用它来执行数组赋值。否则,它将它视为一个字符串并将其作为数组对象的属性存储。基于delnan的评论和DCoder的评论

编辑,这是JavaScript的如何确定它是否是一个数组的适当指数(而不只是一个属性): http://www.ecma-international.org/ecma-262/5.1/#sec-15.4

+0

最后一部分不是特别有用,除非你定义了*究竟是什么*“整数”,什么不是。例如,“05”是一个整数,为什么(不)? – delnan 2013-04-11 19:29:12

4

MDN

也可以引用JavaScript数组索引(例如, 年[“2”]而不是年[2]),尽管这不是必需的。在 年[2]中的2最终被JavaScript 引擎强制转换为字符串,无论如何,通过隐式toString转换。这是 这个原因,“2”和“02”就指的是两个不同的插槽上 多年对象和以下示例记录真实:

console.log(years["2"] != years["02"]); 
a["5"]

所以,你正在访问的阵列,同时在a["05"]在数组对象上设置一个属性。

1

数组也是对象。

通过这样做

a["05"] = 5; 

你正在做同样的事情:作为一个属性点之后指定

a.05 = 5; 

然而,上面会导致语法错误,不能从一个数字开始。

所以,如果你这样做:

a = []; 
a["05"] = 5; 

你仍然有一个空数组,但命名05的的a属性的值为5

xis an array index当且仅当ToString(ToUint32(x))等于x(所以在"05"情况下要求不能满足)。

相关问题