Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is "new.target"?

The ECMAScript 2015 specification mention the keyword (or words?) new.target exactly 3 times - 1 time in 14.2.3:

Normally, Contains does not look inside most function forms However, Contains is used to detect new.target, this, and super usage within an ArrowFunction.

and twice in 14.2.16:

An ArrowFunction does not define local bindings for arguments, super, this, or new.target. Any reference to arguments, super, this, or new.target within an ArrowFunction must resolve to a binding in a lexically enclosing environment

MDN mentions it, but is very vague and the page is incomplete.

Babel doesn't seem to support it. I got syntax errors when trying to use new.target in a function (arrow or others).

What is it, and how is it supposed to be used?

like image 540
Amit Avatar asked Sep 08 '15 06:09

Amit


People also ask

What is JavaScript new?

New keyword in JavaScript is used to create an instance of an object that has a constructor function. On calling the constructor function with 'new' operator, the following actions are taken: A new empty object is created.

What does => mean in JavaScript?

It's a new feature that introduced in ES6 and is called arrow function. The left part denotes the input of a function and the right part the output of that function.

What are Arrow functions?

Arrow functions are a new way to write anonymous function expressions, and are similar to lambda functions in some other programming languages, such as Python. Arrow functions differ from traditional functions in a number of ways, including the way their scope is determined and how their syntax is expressed.

Which one is correct code for Arrow function?

// using arrow functions let x = (x, y) => x * y; using an arrow function.


1 Answers

You didn't find it in the spec because in the syntax definitions it is written with blanks, as new . target. The name of the expression is NewTarget, and you'll find that term a few times around.

NewTarget is the first of the so-called meta properties and can be found in §12.3.8.

Its sole purpose is to retrieve the current value of the [[NewTarget]] value of the current (non-arrow) function environment. It is a value that is set when a function is called (very much like the this binding), and according to §8.1.1.3 Function Environment Records:

If this Environment Record was created by the [[Construct]] internal method, [[NewTarget]] is the value of the [[Construct]] newTarget parameter. Otherwise, its value is undefined.

So, for one thing, finally enables us to detect whether a function was called as a constructor or not.

But that's not its real purpose. So what is it then? It is part of the way how ES6 classes are not only syntactic sugar, and how they allow us inheriting from builtin objects. When you call a class constructor via new X, the this value is not yet initialised - the object is not yet created when the constructor body is entered. It does get created by the super constructor during the super() call (which is necessary when internal slots are supposed to be created). Still, the instance should inherit from the .prototype of the originally called constructor, and that's where newTarget comes into the play. It does hold the "outermost" constructor that received the new call during super() invocations. You can follow it all the way down in the spec, but basically it always is the newTarget not the currently executed constructor that does get passed into the OrdinaryCreateFromConstructor procedure - for example in step 5 of §9.2.2 [[Construct]] for user-defined functions.

Long text, maybe an example is better suited:

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; 
like image 179
Bergi Avatar answered Oct 12 '22 16:10

Bergi