做了一些之后research on这个问题,事实证明,其实有一种解决疯狂的方法。
逗号运算符
从我的测试来看,这一点并不是很明显,但理解有效的示例非常有用。
console.log(source[srcKeys]);
console.log(source[[[[srcKeys]]]]);
console.log(source[[],[[[srcKeys]]]]);
console.log(source[[],[[srcKeys]]]);
console.log(source[[[]],[],srcKeys]);
console.log(source[[[]],[[srcKeys]]]);
您会注意到,这些陈述实际上存在一种最初并不明显的模式。
每个属性访问器要么是一个逗号表达式(它将计算出表达式中的最后一个值 - 通常是一个数组),要么只是一个数组。
console.log(source[srcKeys]); // => array
console.log(source[[[[srcKeys]]]]); // => array
console.log(source[[],[[[srcKeys]]]]); // => comma expression
console.log(source[[],[[srcKeys]]]); // => comma expression
console.log(source[[[]],[],srcKeys]); // => comma expression
console.log(source[[[]],[[srcKeys]]]); // => comma expression
更重要的是,每个数组要么是单元素数组,要么是单元素数组的嵌套数组.
有了这些知识,现在是尝试了解 ECMAScript 规范如何制定评估的好时机property accessors.
属性存取器
我不会再讲那些血淋淋的细节,而是总结一下几乎 99% 的情况下发生的情况:
属性表达式首先转换为字符串(除非它是Symbol自 es6 起),然后返回对具有给定属性名称的值的引用
现在我们知道 JavaScript 将简单地尝试将任何属性访问器转换为字符串,并使用该字符串作为属性名称。
除此之外,数组在转换为字符串时还有一个有趣的行为。您可以阅读此其他内容answer深入了解数组如何转换为属性名称。
不那么秘密的揭露
现在让我们将我们所知道的一切应用到给出的示例中,看看为什么有些有效而有些无效。
首先,让我们看一下不起作用的示例:
console.log(source[[[],[[srcKeys]]]]); // => property accessor expression is [[],[[srcKeys]]]
console.log(source[[[],[],[[srcKeys]]]]); // => property accessor expression is [[],[],[[srcKeys]]]
console.log(source[[[[]],[[srcKeys]]]]); // => property accessor expression is [[[]],[[srcKeys]]]
每个表达式的一个一致的细节是它们都是数组multiple元素。很快就会明白为什么这些没有给我们带来预期的价值,但之前的却给了我们预期的价值。为此,我现在将展示结果toString在所有阵列上。
const source = {
last: "Capulet"
};
const srcKeys = Object.keys(source);
// console.log(source[srcKeys]);
console.log(srcKeys.toString());
// console.log(source[[[[srcKeys]]]]);
console.log([
[
[srcKeys]
]
].toString());
// console.log(source[[],[[[srcKeys]]]]);
console.log(([], [
[
[srcKeys]
]
]).toString());
// console.log(source[[],[[srcKeys]]]);
console.log(([], [
[srcKeys]
]).toString());
// console.log(source[[[]],[],srcKeys]);
console.log(([
[]
], [], srcKeys).toString());
// console.log(source[[[]],[[srcKeys]]]);
console.log(([
[]
], [
[srcKeys]
]).toString());
// console.log(source[[[],[[srcKeys]]]]);
console.log([
[],
[
[srcKeys]
]
].toString());
// console.log(source[[[],[],[[srcKeys]]]]);
console.log([
[],
[],
[
[srcKeys]
]
].toString());
// console.log(source[[[[]],[[srcKeys]]]]);
console.log([
[
[]
],
[
[srcKeys]
]
].toString());
我们终于得到它了。第一个有效的示例的 toString 值为last
,而其余的则没有。