The new.target Property And Why It Is Useful In JavaScript
If the below code blocks do not show up properly due to a recent Tumblr change. View them directly at https://obscurejavascript.tumblr.com/
new.target is a property of an object corresponding to the current instance scope. This is useful to check whether an object was created with new or not. Firstly, not instantiating with new can have confusing outcomes:
'use strict'; function Car() { return this; } Car.prototype.setName = function(name) { this.name = name; }; Car.prototype.getName = function() { return this.name; }; const miata = new Car(); miata.setName('miata'); console.log(miata.getName()); // miata const ferrari = Car(); ferrari.setName('ferrari'); // TypeError: Cannot read property 'setName' of undefined
Basically, when not using new the class function is called like a normal function and does not instantiate an object. So this is undefined. If the return is removed, the result will still be the same since using new will always return an instance of an object.
Anyways, I did not use the new class syntax deliberately. When it is used instead an error will be thrown when Car is called without using new:
class Car { setName(name) { this.name = name; } getName() { return this.name; } } const miata = new Car(); miata.setName('miata'); console.log(miata.getName()); // miata const ferrari = Car(); // TypeError: Class constructor Car cannot be invoked without 'new'
Which is one reason to use the new syntax. But in some cases you will encounter legacy code not in the class syntax that may need to be used that cannot be refactored easily (e.g. complex logic with no tests). So new.target can be used to add that much less confusing class error message without having to convert everything:
function Car() { if (!new.target) { throw(new TypeError("Class constructor Car cannot be invoked without 'new'")); } } Car.prototype.setName = function(name) { this.name = name; }; Car.prototype.getName = function() { return this.name; }; const miata = new Car(); miata.setName('miata'); console.log(miata.getName()); // miata const ferrari = Car(); // TypeError: Class constructor Car cannot be invoked without 'new'
This way JS provides a way of replicating the more strict nature of the class syntax while maintaining strict backwards compatability with the old function syntax based class creation.
Unfortunately, since this is undefined in the above case when called without new the name of the class cannot be automatically determined. So it must be manually given for each legacy syntax class this is done for.
new.target works in all modern browsers
Github Location: https://github.com/Jacob-Friesen/obscurejs/blob/master/2020/newTarget.js











