JavaScript new.target is a metaproperty that lets a function or class constructor detect how it was invoked. It evaluates to the constructor or function that was called with the new operator. When a normal function is called without new, new.target is undefined. This feature is useful for checking constructor calls, understanding inheritance, and creating flexible constructor behavior.

What Is new.target in JavaScript?

new.target is a special syntax introduced in ECMAScript 2015 (ES6). It is called a metaproperty because it is made up of the new keyword, a dot, and the target name. It is not an ordinary property of an object.

When a constructor function is invoked with new, new.target refers to the constructor used by that construction operation. When the same ordinary function is called like a regular function, new.target evaluates to undefined.

Basic Syntax of new.target

You can use new.target inside a function body or a class constructor to inspect the constructor that initiated the call.

function Person(name) {
  console.log(new.target);
  this.name = name;
}

const person1 = new Person("Nadia");
// Logs: [Function: Person] (display may vary)

Person("Rahim");
// Logs: undefined

In the first call, new Person("Nadia") invokes the function as a constructor, so new.target refers to Person. In the second call, Person("Rahim") is a regular function call, so new.target is undefined.

Detecting Whether a Function Is Called with new

One common use of new.target is to prevent a constructor function from being called without the new operator. You can throw a TypeError when the function is invoked incorrectly.

function Employee(name, department) {
  if (!new.target) {
    throw new TypeError("Employee must be called with new.");
  }

  this.name = name;
  this.department = department;
}

const employee1 = new Employee("Ava", "IT");

console.log(employee1.name); // "Ava"

// Throws TypeError:
// const employee2 = Employee("Rafi", "HR");

The condition !new.target is true when the ordinary function is called without new. This check helps avoid accidental calls that would otherwise run the function with an unexpected this value.

Using new.target with Constructor Inheritance

new.target is especially useful when constructor functions are used with inheritance. If a child constructor calls a parent constructor using Parent.call(this), the parent’s new.target is not automatically carried into that ordinary function call. By contrast, when a derived class constructor invokes its base class constructor through super(), the construction operation preserves the most-derived constructor as new.target.

Using new.target in ES6 Classes

JavaScript classes also support new.target inside their constructors. In a base class constructor, it can tell you whether the instance is being created directly from the base class or from a derived class.

class Animal {
  constructor() {
    console.log(new.target.name);
  }
}

class Dog extends Animal {}

class Cat extends Animal {}

const animal = new Animal(); // "Animal"
const dog = new Dog();       // "Dog"
const cat = new Cat();       // "Cat"

When new Animal() runs, new.target is Animal. When new Dog() or new Cat() runs, the base constructor still sees the most-derived constructor: Dog or Cat. This makes it possible for a shared base constructor to identify the class used to create the instance.

Preventing Direct Instantiation of a Base Class

You can use new.target to make a base class reject direct construction while still allowing child classes to extend it. This is one way to create an abstract-like base class in JavaScript.

class Shape {
  constructor() {
    if (new.target === Shape) {
      throw new TypeError("Shape cannot be instantiated directly.");
    }
  }
}

class Circle extends Shape {
  constructor(radius) {
    super();
    this.radius = radius;
  }

  getArea() {
    return Math.PI * this.radius ** 2;
  }
}

// Throws TypeError:
// const shape = new Shape();

const circle = new Circle(5);

console.log(circle.getArea()); // 78.53981633974483

The check rejects new Shape() because the target is exactly Shape. When Circle is constructed, the inherited constructor sees Circle as new.target, so the check passes. JavaScript does not have a built-in abstract class keyword, so this pattern can be used when direct construction should be blocked.

Using new.target Inside Arrow Functions

Arrow functions do not have their own this, arguments, or new.target bindings. They use the corresponding values from their surrounding lexical environment. Therefore, an arrow function nested inside a constructor can access that constructor’s new.target.

function Creator() {
  const getTarget = () => new.target;
  return getTarget();
}

console.log(new Creator() === Creator); // true
console.log(Creator());                 // undefined

The arrow function getTarget does not create a new new.target value. It reads the value from Creator‘s surrounding function environment. When Creator is constructed, the arrow function returns Creator; when it is called normally, it returns undefined.

Using new.target with Reflect.construct()

The Reflect.construct() method creates an object by invoking a constructor. Its optional third argument lets you specify a different new target. The constructor being executed and the constructor referenced by new.target can therefore be different.

function Person(name) {
  this.name = name;
  this.targetName = new.target.name;
}

function Employee() {}

const person = Reflect.construct(
  Person,
  ["Nadia"],
  Employee
);

console.log(person.name);       // "Nadia"
console.log(person.targetName); // "Employee"
console.log(person instanceof Employee); // true
console.log(person instanceof Person);   // false

Here, Person is the constructor whose body runs, but Employee is supplied as the new target. That is why new.target.name is "Employee" and the created object’s prototype is based on Employee.prototype. This advanced capability is useful in frameworks and custom object-construction patterns.

Difference Between new.target and instanceof

new.target and instanceof are related to construction and inheritance, but they answer different questions. new.target is checked from inside a function or constructor to identify the target of the current construction operation. instanceof is an operator used on an object to check whether a constructor’s prototype appears in that object’s prototype chain.

class Animal {}

class Dog extends Animal {}

function checkTarget() {
  return new.target;
}

const dog = new Dog();

console.log(dog instanceof Dog);    // true
console.log(dog instanceof Animal); // true

console.log(new checkTarget() === checkTarget); // true
console.log(checkTarget());                    // undefined

Use new.target to inspect how the current function or constructor was invoked. Use instanceof to inspect an existing object’s relationship to a constructor.

Categorized in:

Javascript, JS Basic,