gpt4 book ai didi

javascript - 在方法内的箭头函数内的箭头函数内使用 `super`

转载 作者:行者123 更新时间:2023-12-03 12:18:04 25 4
gpt4 key购买 nike

我试图弄清楚我在 Node v4.1.1 (V8 v4.5.103.33) 中看到的一些关于 super 的行为和箭头函数是指定的行为,如果是(或者实际上,如果不是),它在 specification 中的位置它说它应该(或不应该)在我遇到的各种情况下工作。

简而言之:使用 super在箭头函数 ( inner ) 内另一个箭头函数 ( outer ) 在方法内有效,除非 outer有参数或变量 inner引用,即使 inner引用 method 的参数或变量.我想知道规范说明关于这一点:它是否应该一直工作,即使 V8 出现故障?没有时间?仅在 V8 当前允许它工作的特定情况下,而不是在它不工作的地方?

这是一个 MCVE:

"use strict";

class Parent {
show(msg) {
console.log(`Parent#show: ${msg}`);
}
}

class Child extends Parent {
method(arg) {
let outer = (x) => {
console.log(`outer: x = ${x}`);
let inner = () => {
super.show(`arg = ${arg}, x = ${x}`);
};
inner();
};
outer(42);
}
}

new Child().method("arg");

那失败了:
$ node test.js/path/test.js:13                super.show(`arg = ${arg}, x = ${x}`);                ^^^^^SyntaxError: 'super' keyword unexpected here    at outer (/path/test.js:16:13)    at Child.method (/path/test.js:18:9)    at Object. (/path/test.js:22:13)    at Module._compile (module.js:434:26)    at Object.Module._extensions..js (module.js:452:10)    at Module.load (module.js:355:32)    at Function.Module._load (module.js:310:12)    at Function.Module.runMain (module.js:475:10)    at startup (node.js:117:18)    at node.js:951:3

If you remove the reference to x that's in inner:

            let inner = () => {
super.show(`arg = ${arg}`); // <== removed x from this
};

它的工作原理和输出:
outer: x = 42Parent#show: arg = arg

To prove to myself that the "works" case wasn't that the functions were being optimized away, I returned them out of the method and called them. Here's that slightly-more complex case (note the comments); this version works:

"use strict";

class Parent2 {
show(msg) {
console.log(`Parent2#show: ${msg}`);
}
}

class Child2 extends Parent2 {
method(arg) {
let flag = Math.random() < 0.5;
console.log(`method called with ${arg}, flag is ${flag}`);
let x = "A"; // **A**
let outer2 = (/*x*/) => { // **B**
//let x = "C"; // **C**
let inner2 = () => {
super.show(`${x}: ${arg} (${flag})`);
};
return inner2;
};
return outer2;
}
}

let o = new Child2().method("arg");
console.log(`type of outer2: ${typeof o}`);
let i = o();
console.log(`type of inner2: ${typeof i}`);
i("B");

输出:

使用 arg 调用的方法,标志为 false
outer2 的类型:函数
inner2 的类型:函数
Parent2#show: A: arg(假)

但是如果我们注释掉标记为 A 的行并取消注释 BC ,它像 MCVE 一样失败。

更多注释:
  • 我要强调的是,您需要嵌套箭头函数。 outer访问 super 没有问题.我不想用另一个大代码块来混淆这个问题,但是如果你添加 super.show(`outer: arg = ${arg}, x = ${x}`);outer 的顶部,它工作得很好。
  • 如您所见,inner使用 method 中的参数和变量(嗯,MCVE 只使用一个 arg),这很好,但只要 inner尝试使用 outer 中的参数或变量,事情闹大了。
  • Babel 和 Traceur 都非常乐意转换 V8 无法运行的情况( herehere ),但这可能只是他们在 V8 正确的情况下出错了(或者,当然,反之亦然) .
  • 它与模板字符串无关; MCVE 之前的版本没有使用它们(并且确实使用了 Promise,这就是我们最终在箭头中使用箭头的方式)。

  • 只是为了强调,问题是这里指定的行为是什么,以及它在规范中的什么地方指定。

    我的直觉告诉我,这只是一个 V8 错误——毕竟,这些东西还为时过早。但无论哪种方式,我只是想弄清楚行为应该是什么,规范是什么。我试着关注它关于 super 的各种不同的部分。和“基础对象”等,坦率地说,我只是不明白。

    最佳答案

    看来这确实是 V8 中的一个错误(现在是 fixed )。 请注意,如果没有嵌套箭头函数,它可以正常工作。
    因此,如果我们要通过文字规范文本来查看这是否是一个错误,让我们从 super 开始。关键字本身:

    12.3.5.3 Runtime Semantics: MakeSuperPropertyReference(propertyKey, strict)

    The abstract operation MakeSuperPropertyReference with arguments propertyKey and strict performs the following steps:

    1. Let env be GetThisEnvironment( ).
    2. If env.HasSuperBinding() is false, throw a ReferenceError exception.
    3. Let actualThis be env.GetThisBinding().
    4. ReturnIfAbrupt(actualThis).
    5. Let baseValue be env.GetSuperBase().
    6. Let bv be RequireObjectCoercible(baseValue).
    7. ReturnIfAbrupt(bv).
    8. Return a value of type Reference that is a Super Reference whose base value is bv, whose referenced name is propertyKey, whose thisValue is actualThis, and whose strict reference flag is strict.

    让我们忽略大部分冗长的东西并担心 GetThisEnvironment():

    8.3.2 GetThisEnvironment ( )

    The abstract operation GetThisEnvironment finds the Environment Record that currently supplies the binding of the keyword this. GetThisEnvironment performs the following steps:

    1. Let lex be the running execution context’s LexicalEnvironment.
    2. Repeat
      a. Let envRec be lex’s EnvironmentRecord.
      b. Let exists be envRec.HasThisBinding().
      c. If exists is true, return envRec.
      d. Let outer be the value of lex’s outer environment reference.
      e. Let lex be outer.

    NOTE The loop in step 2 will always terminate because the list of environments always ends with the global environment which has a this binding.


    现在我们知道箭头函数没有绑定(bind)到 this ,它应该跳过当前函数的环境记录和立即包含它的函数。
    一旦到达“常规”函数,这将停止并继续检索对 super 的引用。根据规范,对象符合预期。
    ECMAScript 规范的项目编辑 Allen Wirfs-Brock 似乎在对 es-discuss mailing list 的回复中确认这是有意的。几年前:

    super is lexically scoped, just like this to the closest enclosing function that defines it. All function definition forms except for arrow functions introduce new this/super bindings so we can just [say] that this/super binds according to the closest enclosing non-arrow function definition.

    关于javascript - 在方法内的箭头函数内的箭头函数内使用 `super`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32943776/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com