`let:let {let:[x = 1]} = [alert(1)]`会发生什么?

时间:2018-04-02 01:44:29

标签: javascript microsoft-edge destructuring labeled-statements

我正在看a talk on JSON hijacking而不是2分钟,我已经不熟悉JavaScript了。

let:let{let:[x=1]}=[alert(1)]

它似乎适用于Edge而只是警告1,但我从来没有遇到let:let语法。我很好奇,我怎么读这个?

1 个答案:

答案 0 :(得分:4)

该视频实际上表示它使用了destructuring assignmentlabels

此代码似乎不适用于Edge以外的浏览器;所以为了使它在其他浏览器中工作,它需要看起来像这样:

let:{let{let:[x=1]}=[alert(1)]}

为什么呢?我们来看看Firefox的控制台:

  

SyntaxError: lexical declarations can't appear in single-statement context

错误所指的“单一语句上下文”是开头let:之后的部分 - let{let:[x=1]}=[alert(1)]。在这种情况下,let之前是标签。没有其他关键字可用作标签:

var: while(false); // => SyntaxError: missing variable name
for: while(false); // => SyntaxError: missing ( after for

然而,其中一些有效:

yield: while(false);
async: while(false);
await: while(false);

然而,在strict mode中,letyield也会因SyntaxError: [keyword] is a reserved identifier而失败。

现在,代码的剩余部分使用了解构:

let {
    let: [x = 1]
  } = [
    alert(1)
  ];

let {内的}只表示对象属性,完全没问题。以下是有效的JS:

let object = {
    let: 2,
    var: 1,
    const: "hello",
    while: true,
    throw: Error
  };

alert(1)被执行,因此您会看到警报。它评估为undefined,因此您拥有:

let {let: [x = 1]} = [undefined];

现在,我们尝试获取let的{​​{1}}属性,该属性本身为[undefined]。此外,该行试图获取该属性的值,并将其进一步解构为数组(因此该值必须是可迭代对象),其第一个元素具有变量名undefined,具有默认值x。由于1[undefined].let,因此无法对其进行解构,因此代码会抛出错误:

  

undefined

工作解构可能看起来像以下一行:

TypeError: [...].let is undefined
let {let: [x = 1]} = {let: [alert(1)]}; // x is now 1 (default value, since first element in right-hand side is undefined)

两者都不会抛出错误,第一个错误会将let {let: [x = 1]} = {let: [2]}; // x is now 2 (defined due to right-hand side) 分配给1,因为右侧数组中的第一个元素是x

部分混淆可能源于嵌套解构,就像这两个片段一样:

undefined
let {a: {b: {c}}} = {a: {b: {c: 3}}}

此处,未创建变量let {a: {b: {c = 1}}} = {a: {b: {c: 3}}} a,仅b,标识符后跟c左手边。 :后面的属性名称基本上指示“在右侧值中找到此属性