12

我正在为极度资源受限的嵌入式设备(http://www.espruino.com)编写一个 JavaScript 解释器,每次我认为我正确地实现了一些 JavaScript 时,我都意识到我错了。

我现在的问题是关于[]. 您将如何正确实现 JavaScript 最基本的部分之一?

我查看了 JavaScript 规范,也许我没有找到正确的位,但我找不到有用的答案。

我之前假设您实际上有两个“映射”——一个用于整数,一个用于字符串。数组长度是最大整数加一的值。然而,这似乎是错误的,根据 jsconsole on chrome:

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"是一个有效的整数 - 即使是八进制。那么为什么它不影响长度呢?

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

有没有人参考用于存储和获取数组或对象中项目的确切算法?看起来应该很简单,但看起来实际上并非如此!

4

4 回答 4

4

MDN

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

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

因此,当您在数组对象上设置属性时,a["5"]您正在访问数组。a["05"]

于 2013-04-11T19:28:20.413 回答
4

正如规格所说,并被其他人指出:

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

这解释了为什么在您的场景中"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

Note: the Zero-fill right shift is the shortest way in JS to have a substitute of ToUint32, shifting a number by zero.

于 2013-04-11T19:56:24.700 回答
3

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

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

根据 delnan 的评论和 DCoder 的评论进行编辑,这就是 JavaScript 确定它是否是数组的适当索引(而不仅仅是一个属性)的方式:http: //www.ecma-international.org/ecma-262/5.1/#sec -15.4

于 2013-04-11T19:27:37.383 回答
1

数组也是对象。

通过做这个

a["05"] = 5;

你正在做同样的事情:

a.05 = 5;

但是,上面会导致语法错误,因为在点之后指定的属性不能以数字开头。

所以如果你这样做:

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

您仍然有一个空数组,但anamed的属性05具有值5

当且仅当等于时,该数字x 是数组索引(因此在不满足该要求的情况下)。ToString(ToUint32(x))x"05"

于 2013-04-11T19:44:37.003 回答