O que é “new.target”?

A especificação ECMAScript 2015 menciona a palavra-chave (ou palavras?) New.target exatamente 3 vezes – 1 vez em 14.2.3 :

Normalmente, Contains não procura dentro da maioria das formas de function No entanto, Contains é usado para detectar new.target , this e super usage em uma ArrowFunction.

e duas vezes em 14.2.16 :

Uma ArrowFunction não define ligações locais para argumentos, super, this ou new.target . Qualquer referência a argumentos, super, this ou new.target em uma ArrowFunction deve resolver para uma binding em um ambiente de inclusão lexical

O MDN menciona isso, mas é muito vago e a página está incompleta.

Babel não parece apoiar isso. Eu tenho erros de syntax ao tentar usar new.target em uma function (seta ou outros).

O que é, e como é que deve ser usado?

Você não o encontrou na especificação porque nas definições de syntax ele é escrito com espaços em branco, como new . target new . target . O nome da expressão é NewTarget e você encontrará esse termo algumas vezes.

NewTarget é a primeira das chamadas propriedades meta e pode ser encontrada em §12.3.8.

Seu único objective é recuperar o valor atual do valor [[NewTarget]] do ambiente de function atual (sem seta). É um valor que é definido quando uma function é chamada (muito parecida com this binding) e, de acordo com §8.1.1.3 Registros do Ambiente de Função :

Se este registro de ambiente foi criado pelo método interno [[Construct]] , [[NewTarget]] é o valor do parâmetro [[Construct]] newTarget . Caso contrário, seu valor é undefined .

Então, por um lado, finalmente nos permite detectar se uma function foi chamada como um construtor ou não.

Mas esse não é o seu propósito real. O que é isso então? É parte do modo como as classs ES6 não são apenas açúcar sintático e como elas nos permitem herdar de objects internos. Quando você chama um construtor de class via new X , this valor ainda não está inicializado – o object ainda não foi criado quando o corpo do construtor é inserido. Ele é criado pelo super construtor durante a chamada super() (que é necessária quando slots internos devem ser criados). Ainda assim, a instância deve herdar do .prototype do construtor originalmente chamado, e é aí que newTarget entra no jogo. Ele mantém o construtor “mais externo” que recebeu a new chamada durante as chamadas super() . Você pode seguir todo o caminho na especificação, mas basicamente é sempre o newTarget não o construtor atualmente executado que é passado para o procedimento OrdinaryCreateFromConstructor – por exemplo, na etapa 5 do §9.2.2 [[Construct]] para o usuário funções definidas.

Texto longo, talvez um exemplo seja mais adequado:

 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; 

Ele é basicamente uma maneira melhor de detectar quando um construtor é chamado sem new .

De http://www.2ality.com/2015/02/es6-classs-final.html :

new.target é um parâmetro implícito que todas as funções possuem. É para o construtor chamar o que é this para chamadas de método.

Então eu posso escrever:

 function Foo() { if (!new.target) throw "Foo() must be called with new"; ... } 

Há mais detalhes sobre como isso funciona e mais contextos nos quais isso é útil, mas deixaremos isso aqui.

Para algumas annotations sobre o new.target , consulte https://esdiscuss.org/notes/2015-01-27 .