Ответ 1
Вы не нашли его в спецификации, потому что в определениях синтаксиса он написан с пробелами, как 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
процедура - например, в шаг 5 из §9.2.2 [[Construct]] для пользовательских функций.
Длинный текст, возможно, пример лучше подходит:
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;