Why use new.target inside a function in JavaScript – Simplified

There are four invocation patterns in JavaScript, which means you can call a function in four possible ways. They are,

  1. Function Invocation Pattern
  2. Constructor Invocation Pattern
  3. Method Invocation Pattern
  4. Indirect Invocation Pattern

Essentially, these four-invocation patterns determine the value of ‘this’ object inside a function.  Let us consider the function created below,


function add(num1, num2) {
    console.log(this); // global object 
}
 
let a = add(8, 9); 

In the above code, you are calling function add as a function, hence adhering to the Function Invocation Pattern. In the FIP, the value of ‘this’ object inside the function is always the global object.

If you modify the above code a bit,


function add(data) {
    this.console = data;
    return data;
}
 
let a = add('console');
console.log(a);

On running the above code, JavaScript throws you, TypeError that console .log is not a function.

Now, you get this error because, by mistake, you have overridden the console method of the global object by your console property. Perhaps you wanted to create a new object and add console property to that.

When you call a function adhering to the Constructor Invocation Pattern using the new operator, the value of ‘this’ inside the function is the newly created object.


function add(data) {
    this.console = data;
    return data;
}
 
let a = new add('console');
console.log(a);

Here, a newly created object represents the value of ‘this’ inside the function add. So, you are adding console property to the newly created object instead of the global object. Hence JavaScript does not throw an error, and you get the output as below,

You can create an object in multiple ways, and the Constructor Invocation Pattern is one of them. So you can create a constructor to create products as below,


function Product(title, price) {
    this.title = title;
    this.price = price;
}
 
let p1 = new Product('Pen', 200);
console.log(p1);
 
let p2 = new Product('Pencil', 100);
console.log(p2);

As you are calling Product function adhering to the CIP using the new, it acts as a constructor, and inside it, the value of ‘this’ object is newly created object.  You will get the output as below,

Now the problem is what If you forget to call the Product constructor with the new operator like below,


function Product(title, price) {
    this.title = title;
    this.price = price;
}
 
let p1 = Product('Pen', 200);
console.log(p1);
 
let p2 = Product('Pencil', 100);
console.log(p2);

There are a couple of important observations,

  1. JavaScript does not complain about it
  2. It adds two properties title and price to the global object
  3. It returns undefined

As you see for JavaScript, adding a property to a global object is not an error. You can reinforce rule not to add a property to the global object by running the JavaScript in strict mode,


'use strict'
 
function Product(title, price) {
    this.title = title;
    this.price = price;
}
 
let p1 = Product('Pen', 200);
console.log(p1);
 
let p2 = Product('Pencil', 100);
console.log(p2);

Here JavaScript throws TypeError as below,

It looks good, but what if you cannot run JavaScript in strict mode. In that case, how would you prevent mistakenly adding a property to a global object and ensuring a function meant to be a constructor is always called using the new operator?

You can do that by using new.target


function Product(title, price) {
    if (!new.target) {
        throw "Product()' is a constructor, and must be called with new"
    }
    this.title = title;
    this.price = price;
}
 
try {
    let p1 = Product('Pen', 200);
    console.log(p1);
    let p2 = Product('Pencil', 100);
    console.log(p2);
}
catch (error) {
    console.log(error);
}

By using new. target, you ensure

  • A function meant to be a constructor is always called with new operator
  • By mistake doesn’t add properties to the global object
  • Force a function to be only called as a constructor.

Now I hope you understand the real purposes of new.target. I hope you like this post. Thanks for reading.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s