您没有在规范中找到它,因为在语法定义中它是用空格编写的,如new . target
. 表达式的名称是NewTarget
,您会多次发现该术语。
NewTarget是第一个所谓的元属性,可以在 §12.3.8 中找到。
它的唯一目的是检索当前(非箭头)函数环境的[[NewTarget]]值的当前值。它是在调用函数时设置的值(非常类似于this
绑定),并且根据§8.1.1.3 Function Environment Records:
如果此环境记录是由[[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;