在使用Object.create创建的对象中使用super

nil*_*ils 5 javascript ecmascript-6

今天早上我看到了来自ŠimeVidas推文,他提出了以下使用super对象文字的可能性:

let A = {
  run() {
    console.log('A runs');
  }
};

let B = {
  run() {
    super.run();
  }
};

Object.setPrototypeOf(B, A);

B.run(); // A runs
Run Code Online (Sandbox Code Playgroud)

这种方法很有效,而且B.__proto__ = A;在Firefox和Chrome中也可以分配.

所以我想我也可以这样做Object.create:

let A = {
  run() {
    console.log('A runs');
  }
};

let B = Object.create(A);
B.run = function() { super.run() };
Run Code Online (Sandbox Code Playgroud)

不幸的是,这导致两个Firefox出错:

SyntaxError:使用超级属性访问仅在方法中的方法或eval代码中有效

和Chrome:

未捕获的SyntaxError:'super'关键字在这里意外

当我尝试将属性描述符对象传递给第二个参数时,会发生同样的情况Object.create.

在语义上,它们似乎都与我相等,所以我不太确定发生了什么(是因为对象字面量?).

现在我想知道,这个标准行为是否准确定义(规格参考赞赏)?是否有一些实现缺失Object.create,或者对象文字首先不起作用?

nil*_*ils 6

ES2015规范的编辑Allen Wirfs-Brock非常友好地在twitter上回答了我的问题.

为什么这是一个错误?

超级属性引用只能出现在类def或obj中的"简明方法"中http://tc39.github.io/ecma262/#sec-function-definitions-static-semantics-early-errors

在规范的那一部分,静态语义:早期错误,有四点似乎是相关的:

  • 如果FormalParameters包含SuperProperty,则为语法错误.
  • 如果FunctionBody包含SuperProperty为true,则为语法错误.
  • 如果FormalParameters包含SuperCall为true,则为语法错误.
  • 如果FunctionBody包含SuperCall为true,则为语法错误.

因此,超级属性调用既不允许在函数参数中,也不在常规函数体中.因此我的问题.

为什么有必要使用方法定义?

原因是super需要从方法到其包含对象的反向链接.http://tc39.github.io/ecma262/#sec-runtime-semantics-definemethod

意思是,如果我在一个方法中有一个超级调用,并且我将该方法分配给另一个变量,它仍然必须工作:

let B = {
  run() {
    super.run();
  },
  walk() {
    console.log(typeof this.run);
  }
};

var run = B.run;
run(); // the 'super' binding still works, thanks to the internal MakeMethod

var walk = B.walk;
walk(); // 'undefined': the 'this' binding on the other hand is lost, as usual
Run Code Online (Sandbox Code Playgroud)

这在定义方法语义的部分的步骤7中指定,当前对于对象的常规分配不会发生这种情况:

  1. 执行MakeMethod(闭包,对象).

这些语义会在未来发生变化吗?

反向链接至关重要.动态设置它的方法被考虑了,可能会再次出现.遗漏了b/c容易出错

因此,有可能.toMethod可以将可以设置对象super引用的东西引入到语言中,这使得我的初始示例成为Object.create可能.