new.target
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since September 2017.
Thenew.target meta-property lets you detect whether a function or constructor was called using thenew operator. In constructors and functions invoked using thenew operator,new.target returns a reference to the constructor or function thatnew was called upon. In normal function calls,new.target isundefined.
In this article
Try it
function Foo() { if (!new.target) { throw new TypeError("calling Foo constructor without new is invalid"); }}try { Foo();} catch (e) { console.log(e); // Expected output: TypeError: calling Foo constructor without new is invalid}Syntax
new.targetValue
new.target is guaranteed to be a constructable function value orundefined.
- In class constructors, it refers to the class that
newwas called upon, which may be a subclass of the current constructor, because subclasses transitively call the superclass's constructor throughsuper(). - In ordinary functions, if the function is constructed directly with
new,new.targetrefers to the function itself. If the function is called withoutnew,new.targetisundefined. Functions can be used as the base class forextends, in which casenew.targetmay refer to the subclass. - If a constructor (class or function) is called via
Reflect.construct(), thennew.targetrefers to the value passed asnewTarget(which defaults totarget). - Inarrow functions,
new.targetis inherited from the surrounding scope. If the arrow function is not defined within another class or function which has anew.targetbinding, then a syntax error is thrown. - Instatic initialization blocks,
new.targetisundefined.
Description
Thenew.target syntax consists of the keywordnew, a dot, and the identifiertarget. Becausenew is areserved word, not an identifier, this is not aproperty accessor, but a special expression syntax.
Thenew.target meta-property is available in all function/class bodies; usingnew.target outside of functions or classes is a syntax error.
Examples
>new.target in function calls
In normal function calls (as opposed to constructor function calls),new.target isundefined. This lets you detect whether a function was called withnew as a constructor.
function Foo() { if (!new.target) { throw new Error("Foo() must be called with new"); } console.log("Foo instantiated with new");}new Foo(); // Logs "Foo instantiated with new"Foo(); // Throws "Foo() must be called with new"new.target in constructors
In class constructors,new.target refers to the constructor that was directly invoked bynew. This is also the case if the constructor is in a parent class and was delegated from a child constructor.new.target points to the class thatnew was called upon. For example, whenb was initialized usingnew B(), the name ofB was printed; and similarly, in case ofa, the name of classA was printed.
class A { constructor() { console.log(new.target.name); }}class B extends A { constructor() { super(); }}const a = new A(); // Logs "A"const b = new B(); // Logs "B"new.target using Reflect.construct()
BeforeReflect.construct() or classes, it was common to implement inheritance by passing the value ofthis, and letting the base constructor mutate it.
function Base() { this.name = "Base";}function Extended() { // Only way to make the Base() constructor work on the existing // `this` value instead of a new object that `new` creates. Base.call(this); this.otherProperty = "Extended";}Object.setPrototypeOf(Extended.prototype, Base.prototype);Object.setPrototypeOf(Extended, Base);console.log(new Extended()); // Extended { name: 'Base', otherProperty: 'Extended' }However,call() andapply() actuallycall the function instead ofconstructing it, sonew.target has valueundefined. This means that ifBase() checks whether it's constructed withnew, an error will be thrown, or it may behave in other unexpected ways. For example, you can't extendMap this way, because theMap() constructor cannot be called withoutnew.
All built-in constructors directly construct the entire prototype chain of the new instance by readingnew.target.prototype. So to make sure that (1)Base is constructed withnew, and (2)new.target points to the subclass instead ofBase itself, we need to useReflect.construct().
function BetterMap(entries) { // Call the base class constructor, but setting `new.target` to the subclass, // so that the instance created has the correct prototype chain. return Reflect.construct(Map, [entries], BetterMap);}BetterMap.prototype.upsert = function (key, actions) { if (this.has(key)) { this.set(key, actions.update(this.get(key))); } else { this.set(key, actions.insert()); }};Object.setPrototypeOf(BetterMap.prototype, Map.prototype);Object.setPrototypeOf(BetterMap, Map);const map = new BetterMap([["a", 1]]);map.upsert("a", { update: (value) => value + 1, insert: () => 1,});console.log(map.get("a")); // 2Note:In fact, due to the lack ofReflect.construct(), it is not possible to properly subclass built-ins (likeError subclassing) when transpiling to pre-ES6 code.
However, if you are writing ES6 code, prefer using classes andextends instead, as it's more readable and less error-prone.
class BetterMap extends Map { // The constructor is omitted because it's just the default one upsert(key, actions) { if (this.has(key)) { this.set(key, actions.update(this.get(key))); } else { this.set(key, actions.insert()); } }}const map = new BetterMap([["a", 1]]);map.upsert("a", { update: (value) => value + 1, insert: () => 1,});console.log(map.get("a")); // 2Specifications
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-built-in-function-objects> |