按照 ECMAScript 规范理解 JavaScript super() 调用

Understanding JavaScript super() invocations by following the ECMAScript specification

代码

class Parent {
  constructor() {}
}

class Child extends Parent {
  constructor() {
    super();
  }
}

背景

当我试图准确理解 class 构造函数中的 super() 调用是如何工作时,我遵循了以下 ECMAScript 操作顺序:

  1. new Child() calls ChildConstructor.[[Construct]]
  2. kindderived(早先在 14.5.15 中设置),因此没有绑定新的 this
  3. OrdinaryCallEvaluateBody 被调用,最终评估 Child class 构造方法的主体,其中 super() 是第一条语句
  4. super() calls ParentConstructor.[[Construct]],这会将我们带回 步骤 3,这次只是将 kind 作为 base
  5. 由于 kind 现在是 base,一个新的 this 绑定被创建并绑定到 Environment RecordParent 构造函数
  6. 创建的新 函数环境
  7. Parent 构造函数主体的其余部分执行,一旦完成控制流回 Child.[[Construct]] 从第 11 步继续执行
  8. 最后,Child.[[Construct]] 尝试 return envRec.GetThisBinding

问题

Child.[[Construct]]step 6 中创建的 Child 构造函数的 Environment Record 没有 this 绑定( [[ThisBindingStatus]] 未初始化的 )。因此,当我们尝试在步骤 8 中执行 envRec.GetThisBinding 时,据我所知,我们应该得到一个 ReferenceError (as specified here).

我在这里错过了什么?我似乎不明白为什么 Child 构造函数不会抛出错误,事实上如果 Child 构造函数的 [[ThisValue]] 被设置了。

您错过了 super() link 中的一个步骤:

  1. Let newTarget be GetNewTarget().
  2. Assert: Type(newTarget) is Object.
  3. Let func be ? GetSuperConstructor().
  4. Let argList be ArgumentListEvaluation of Arguments.
  5. ReturnIfAbrupt(argList).
  6. Let result be ? Construct(func, argList, newTarget).
  7. Let thisER be GetThisEnvironment( ).
  8. Return ? thisER.BindThisValue(result).

步骤 6 如您所述调用 ParentConstructor.[[Construct]],但随后第 8 步会将 Child 构造函数主体中的 this 绑定设置为构造值,因此当envRec.GetThisBindingChildConstructor.[[Construct]] 结束时运行,this 绑定将在那里