object[[["key"]]] 如何计算为 javascript 中的 object["key"]?
How does object[[["key"]]] evaluate to object["key"] in javascript?
鉴于对象 foo
具有有效的 属性 bar
,为什么 javascript 评估以下为真?
foo[[[["bar"]]]] === foo["bar"]
根据运算符的优先级,我认为 foo[[[["bar"]]]]
正在尝试以数组 [[["bar"]]]
作为键来访问 属性,但为什么仍然 "flatten down"与 foo["bar"]
?
相同
我的同事说 javascript 解析器有括号简化功能,忽略了额外的括号。我不认为这是真的,因为将 [[["foo"]]]
保存到变量 test
会得到相同的结果:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
语言或解析器的哪个方面导致了这种行为?谢谢!
让我们逐步了解如何评估 foo[[[["bar"]]]]
:
foo[...]
中最外面的括号表示a 属性
存取器。因此,表达式 foo[[[["bar"]]]]
转换为
访问名称为 [[["bar"]]]
的 foo
的 属性。
根据ECMA standard,进行抽象操作
ToPropertyKey(name)然后用来转名字[[["bar"]]]
进入 属性 键值:
A property key value is either an ECMAScript String value or a Symbol
value.
名称[[["bar"]]]
不是Symbol类型,因此被转换
成一个字符串。通过 连接数组的所有内容将数组转换为字符串
字符串转换值:
[[["bar"]]].toString() === "bar"
这最终意味着我们的 属性 键实际上变成了 "bar"
:
foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
JavaScript 括号表示法接受表达式,但它总是将该表达式的值转换为字符串。因此,如果您传入一个数组,它会尝试将其转换为字符串。在您的情况下,您传递的是数组 [[["bar"]]]
和 [[["bar"]]].toString() === "bar"
.
如果您想知道为什么 [[["bar"]]].toString() === "bar"
,那是因为当数组 arr
隐式转换为字符串时,就像调用 arr.join(',')
一样。也就是说,它的每个元素都被转换为字符串,然后以逗号分隔的字符串连接起来。当数组只有一个元素时,数组的字符串表示就是该元素的字符串表示。在您的例子中,您的数组 ([[["bar"]]]
) 有一个元素:[["bar"]]
。
该数组也转换为字符串,并且由于它也是一个元素数组,因此它的字符串表示形式是该单个元素的字符串表示形式:["bar"]
.
["bar"]
也是一个数组,只有一个元素,是一个字符串,所以["bar"]
的字符串表示就是"bar"
.
归结为:[[["bar"]]].toString() === "bar"
和foo[[[["bar"]]]]
等同于foo[[[["bar"]]].toString()]
。
您还会发现:
foo[[[[1]],[2]]] === foo["1,2"]
因为:[[[1]],[2]].toString() === "1,2"
.
鉴于对象 foo
具有有效的 属性 bar
,为什么 javascript 评估以下为真?
foo[[[["bar"]]]] === foo["bar"]
根据运算符的优先级,我认为 foo[[[["bar"]]]]
正在尝试以数组 [[["bar"]]]
作为键来访问 属性,但为什么仍然 "flatten down"与 foo["bar"]
?
我的同事说 javascript 解析器有括号简化功能,忽略了额外的括号。我不认为这是真的,因为将 [[["foo"]]]
保存到变量 test
会得到相同的结果:
> test = [[["bar"]]]
[Array[1]]
> foo["bar"] = 5
5
> foo[test]
5
语言或解析器的哪个方面导致了这种行为?谢谢!
让我们逐步了解如何评估 foo[[[["bar"]]]]
:
foo[...]
中最外面的括号表示a 属性 存取器。因此,表达式foo[[[["bar"]]]]
转换为 访问名称为[[["bar"]]]
的foo
的 属性。根据ECMA standard,进行抽象操作 ToPropertyKey(name)然后用来转名字
[[["bar"]]]
进入 属性 键值:A property key value is either an ECMAScript String value or a Symbol value.
名称
[[["bar"]]]
不是Symbol类型,因此被转换 成一个字符串。通过 连接数组的所有内容将数组转换为字符串 字符串转换值:[[["bar"]]].toString() === "bar"
这最终意味着我们的 属性 键实际上变成了
"bar"
:foo[[[["bar"]]]] === foo[[[["bar"]]].toString()] === foo["bar"]
JavaScript 括号表示法接受表达式,但它总是将该表达式的值转换为字符串。因此,如果您传入一个数组,它会尝试将其转换为字符串。在您的情况下,您传递的是数组 [[["bar"]]]
和 [[["bar"]]].toString() === "bar"
.
如果您想知道为什么 [[["bar"]]].toString() === "bar"
,那是因为当数组 arr
隐式转换为字符串时,就像调用 arr.join(',')
一样。也就是说,它的每个元素都被转换为字符串,然后以逗号分隔的字符串连接起来。当数组只有一个元素时,数组的字符串表示就是该元素的字符串表示。在您的例子中,您的数组 ([[["bar"]]]
) 有一个元素:[["bar"]]
。
该数组也转换为字符串,并且由于它也是一个元素数组,因此它的字符串表示形式是该单个元素的字符串表示形式:["bar"]
.
["bar"]
也是一个数组,只有一个元素,是一个字符串,所以["bar"]
的字符串表示就是"bar"
.
归结为:[[["bar"]]].toString() === "bar"
和foo[[[["bar"]]]]
等同于foo[[[["bar"]]].toString()]
。
您还会发现:
foo[[[[1]],[2]]] === foo["1,2"]
因为:[[[1]],[2]].toString() === "1,2"
.