为什么for...in循环中的变量是字符串?

4

我之前使用for...in循环来记录数值,然后我发现for...in循环中的变量(在这种情况下是i)是一个字符串。

for (var i in ['a', 'b', 'c']) {
  console.log(i, typeof i)
}

我在ECMAScript规范中搜索了“for-in、for-of和for-await-of语句”部分,但没有找到关于这个的任何信息。
我的问题是,规范中是否有关于这个的内容?如果没有,为什么它是一个字符串?

i是你放进去的东西!?如果你有一个字符串数组,那么i将被分配一个字符串。如果你使用for (var i in [1, 2, 3]),那么i将成为一个整数。 - Dominique Fortin
1
@DominiqueFortin 我认为数组的类型与此无关。也许你想到了 for...of 循环? - shreyasm-dev
i 不是数组,它将被赋值为数组的一个元素。 - Dominique Fortin
@DominiqueFortin 我知道这一点,但我不明白这句话的意思 - “你有一个字符串数组,所以i将被分配一个字符串” - 为什么? - shreyasm-dev
这只是一个简化,但它会帮助你理解。for (var i in [1,2,3]) {} 相当于 var arr = [1,2,3]; for(var z = 0; z < arr.length; ++z) {var i = arr[z]; ... } - Dominique Fortin
1个回答

6

for..in 调用 EnumerateObjectProperties,它会:

返回一个迭代器对象 (26.1.1.2),其 next 方法迭代 O 的所有可枚举属性的字符串键。迭代器对象不能直接被 ECMAScript 代码访问。枚举属性的机制和顺序没有明确定义,但必须符合以下规则。

所有对象属性都是字符串或符号。即使是数组上可以像使用数字一样设置和检索的属性,在检索时也被解释为字符串(并在通过 for..in 或其他属性枚举方法如 Object.keysObject.getOwnPropertyNames 检索时作为字符串检索)。您还可以查看 [[OwnPropertyKeys]](),其中提到:

返回列表中每个元素的类型为 String 或 Symbol。

例如,在 Array.prototype.push 中,您可以看到

5. For each element E of items, do:
  a. Perform ? Set(O, ! ToString(len), E, true).

属性赋值总是会设置一个字符串或符号类型的属性。(参见 isPropertyKey - 如果参数的类型为字符串,则返回true。如果参数的类型为符号,则返回true。否则返回false)。

1
可以这样说,Symbol键不被for..in枚举的原因是它早于Symbol出现,还是有其他原因?我曾经知道... - Aluan Haddad
2
听起来很有可能 - 如果一个对象被for..in迭代,而2013年编写的代码不理解符号,它可能会抛出错误,因此也许省略了符号以避免破坏向后兼容性。 - CertainPerformance

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接