I was struggling to decide what to write about this week, so yesterday morning I had a browse through the MDN Web Docs. To my delight, I discovered something I never knew about: the new.target pseudo-property. You can use it to detect if a function was invoked as a constructor, which is awesome!

The new.target pseudo-property is available to all functions. If a function is invoked as a constructor (using the new keyword), it refers to the function itself; otherwise, it's just undefined. Let's look at an example:

/**
* Represents a person.
* @constructor
* @param {string} name - The person's name.
*/

function Person(name) {
// If not invoked as a constructor, throw an error
if (!new.target) {
throw new TypeError("Person constructor cannot be invoked without 'new'");
}

// Otherwise, assign the name property
this.name = name;
}

new Person("SpongeBob"); // Person {name: "SpongeBob"}

Person("SpongeBob"); // Uncaught TypeError: Person constructor cannot be invoked without 'new'

In this code snippet, we combine the logical NOT operator (!) with the new.target pseudo-property to check if the function wasn't invoked as a constructor (using the new keyword). If so, we throw a TypeError. Otherwise, we carry on as normal and assign the name property to the Person object we're constructing.

Now let's rewrite the constructor function using a class. While we can use the new.target pseudo-property inside a class' constructor() method, it's not necessary for this specific purpose. This is because it will already throw an error if we try to invoke the constructor without the new keyword:

/**
* Represents a person.
*/

class Person {
/**
* Create a new person.
* @param {string} name - The person's name.
*/

constructor(name) {
this.name = name;
}
}

new Person("SpongeBob"); // Person {name: "SpongeBob"}

Person("SpongeBob"); // Uncaught TypeError: Class constructor Person cannot be invoked without 'new'

In this code snippet, notice that we don't use the new.target pseudo-property within the class' constructor() method, but it still throws an error when we try to invoke it without the new keyword.

The new.target pseudo-property is supported in all modern browsers, but not IE.