什么是"new.target"?

Ami*_*mit 25 javascript ecmascript-6

ECMAScript 2015规范提到关键字(或单词?)new.target正好3次 - 在14.2.3中 1次:

通常,Contains不会查看大多数函数表单但是,Contains用于检测ArrowFunction中的new.target,this和super用法.

14.2.16中两次:

ArrowFunction不为arguments,super,this或new.target定义本地绑定.对ArrowFunction中的参数,super,this或new.target的任何引用 都必须解析为词汇封闭环境中的绑定

MDN提到它,但非常模糊,页面不完整.

巴别塔似乎不支持它.尝试在函数(箭头或其他)中使用new.target时出现语法错误.

它是什么,它应该如何使用?

Ber*_*rgi 34

你没有在规范中找到它,因为在语法定义中它是用空格写的,如new . target.表达式的名称是NewTarget,你会发现这个术语几次.

NewTarget是所谓的元属性中的第一个,可以在§12.3.8中找到.

其唯一目的是检索当前(非箭头)函数环境的[[NewTarget]]值的当前值.它是在调用函数时设置的值(非常类似于this绑定),并且根据§8.1.1.3 函数环境记录:

如果此环境记录由[[Construct]]内部方法创建,则[[NewTarget]][[Construct]] newTarget参数的值.否则,它的值是undefined.

因此,一方面,最终使我们能够检测函数是否被调用为构造函数.

但这不是它的真正目的.那么它是什么呢?这是ES6类不仅仅是语法糖,以及它们如何允许我们继承内置对象的方式的一部分.当您class通过构造函数调用时new X,该this值尚未初始化 - 在输入构造函数体时尚未创建对象.它确实是在super()调用期间由超级构造函数创建的(当应该创建内部插槽时这是必需的).尽管如此,实例应该继承自.prototype最初调用的构造函数,而这正是newTarget进入游戏的地方.它确实持有在接收new呼叫期间的"最外层"构造函数super()调用.你可以在规范中一直遵循它,但基本上它始终是newTarget不是当前执行的构造函数,而是传递给OrdinaryCreateFromConstructor过程 - 例如,在用于用户定义函数的§9.2.2 [[Construct]]的步骤5中.

长文本,可能是一个更好的例子:

class Parent {
    constructor() {
        // implicit (from the `super` call)
        //    new.target = Child;
        // implicit (because `Parent` doesn't extend anything):
        //    this = Object.create(new.target.prototype);
        console.log(new.target) // Child!
    }
}
class Child extends Parent {
    constructor() {
        // `this` is uninitialised (and would throw if accessed)
        // implicit (from the `new` call):
        //    new.target = Child 
        super(); // this = Reflect.construct(Parent, [], new.target);
        console.log(this);
    }
}
new Child;
Run Code Online (Sandbox Code Playgroud)

  • @Amit:我认为 - 它是多个令牌,它们总是可以通过空格分开.编写`console是有效的ES.log(...)`以及:-)当然没有人这样做 - 除了方法链接时换行... (3认同)
  • @Asad:你不能在`super()`调用之前访问`this` - 当你尝试引用它时,它会抛出一个`ReferenceError`. (3认同)
  • 所以这意味着它在函数内编写`console.log(new . target)`(带空格)的有效语法? (2认同)
  • @Maximus不是“子”,而是“子”构造函数本身。我们希望新实例继承自Child.prototype对象。 (2认同)

小智 8

它主要用于检测何时调用构造函数的更好方法new.

来自http://www.2ality.com/2015/02/es6-classes-final.html:

new.target是所有函数都具有的隐式参数.它是构造函数调用什么this是方法调用.

所以我可以写:

function Foo() {
  if (!new.target) throw "Foo() must be called with new";
  ...
}
Run Code Online (Sandbox Code Playgroud)

关于它是如何工作的更多细节,以及它有用的更多上下文,但我们将它留在这里.

有关会议记录new.target,请参阅https://esdiscuss.org/notes/2015-01-27.

  • @Asad构造函数**是一个用`new`调用的常规函数​​. (6认同)