代码之家  ›  专栏  ›  技术社区  ›  Ced

“let:let{let:[x=1]}=[警报(1)]`?

  •  4
  • Ced  · 技术社区  · 6 年前

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

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

    它似乎在边缘上工作,只是发出警报 1 但我从来没有遇到过 let:let 语法。我很好奇,我该怎么读这个?

    1 回复  |  直到 6 年前
        1
  •  5
  •   Sebastian Simon SamB    6 年前

    视频实际上说它使用 destructuring assignment labels

    此代码在Edge以外的浏览器中似乎不起作用;因此,要使其在其他浏览器中工作,需要如下所示:

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

    为什么?让我们看看Firefoxs控制台:

    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 然而 允许 yield 也会失败 SyntaxError: [关键字] is a reserved identifier

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

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

    这个 允许 内部 { } 只表示一个对象属性,这是完全正确的。以下是有效的JS:

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

    alert(1) 执行,因此您可以看到警报。其计算结果为 undefined ,因此您有:

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

    现在,这是为了 允许 的属性 [undefined] ,其本身就是 未定义 。此外,此行试图获取该属性的值,并将其进一步分解为具有变量名的数组(因此该值必须是iterable对象) x 对于其第一个元素,使用默认值 1 。自从 [undefined].let 未定义 ,它不能被分解,因此代码会抛出错误:

    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个 ,因为右侧数组中的第一个元素是 未定义


    部分混淆可能源于嵌套的解构,如以下两个片段:

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

    这里没有变量 a b 仅创建 c ,它是标识符 后跟a : 在左侧。后跟 : 基本上指导任务 在右侧值中查找此属性