new Keyword – What Is the new Operator in JavaScript?
Whenever you use the new keyword on a constructor, the keyword does the following:
- It creates a new object instance from the constructor.
- It shares the constructor’s
prototypeproperty with the newly created object.
Syntax of the new Keyword
Section titled “Syntax of the new Keyword”We use the new keyword with a constructor function or class. Here is the syntax:
new Constructor(argument);You can omit the parentheses if you pass no argument to the constructor.
new Constructor;Note the following:
- We used an uppercase C in the snippet above because developers typically use capital letters to begin a constructor’s name. This convention helps to differentiate a constructor from other functions.
- You can use the
newkeyword on JavaScript functions or classes. - You can only invoke a JavaScript class with the
newkeyword—otherwise, the browser will throw aTypeError. - Whatever function (or class) you call with the
newkeyword becomes a constructor function (or class). For instance, thenew createBookcode below makescreateBooka constructor function.
function createBook() {}const book1 = new createBook();console.log(book1);The snippet above used the new keyword to construct a new object from createBook(). Therefore, the book1 object is an instance of the createBook() constructor function.
So, now that we know what the new keyword does, we can discuss how it works.
How Does the new Keyword Work?
Section titled “How Does the new Keyword Work?”Here’s what happens whenever you use the new keyword with a constructor:
1. Create empty object
Section titled “1. Create empty object”The computer creates an empty JavaScript object in its memory.
{}2. Add dunder proto
Section titled “2. Add dunder proto”JavaScript adds a dunder ([[Prototype]]) proto to the newly created object.
{ [[Prototype]]: null}3. Initialize the dunder proto
Section titled “3. Initialize the dunder proto”The computer initializes the dunder proto with the new object’s constructor’s prototype.
{ [[Prototype]]: {...}: constructor: keyword ConstructorName() [[Prototype]]: Object {...}}constructorreferences the constructor function (or class) itself.[[Prototype]]references theprototypeproperty that the function (or class) inherited from its own constructor.
Therefore, Constructor.prototype is equivalent to objectInstance.[[Prototype]].
Here’s an example:
// Define a constructor function:function CompanyProfile() {}
// Create an object based on the CompanyProfile function:const bestWebsite = new CompanyProfile();
// Check bestWebsite's dunder proto's content:Object.getPrototypeOf(bestWebsite);
// The invocation above will return:{...}: constructor: function CompanyProfile() [[Prototype]]: Object {...}
// Check if CompanyProfile's prototype is equivalent to bestWebsite's dunder proto:CompanyProfile.prototype === Object.getPrototypeOf(bestWebsite);
// The invocation above will return: trueYou can see that CompanyProfile.prototype returned the same value as Object.getPrototypeOf(bestWebsite). The reason is that bestWebsite’s dunder proto contains the prototype that the object inherited from its constructor (CompanyProfile).
4. Execute the constructor
Section titled “4. Execute the constructor”The new operator’s fourth task is to invoke the constructor on which you used it.
5. Bind the constructor’s this keyword
Section titled “5. Bind the constructor’s this keyword”The computer binds the constructor’s this keyword to the newly created object.
6. Return a non-primitive value
Section titled “6. Return a non-primitive value”The computer closes the constructor’s invocation by returning a non-primitive value.
Important Stuff to Know about the new Keyword
Section titled “Important Stuff to Know about the new Keyword”Here are three essential facts to remember when using the new keyword.
1. Beware of the return keyword
Section titled “1. Beware of the return keyword”Suppose your constructor uses the return keyword to produce an object. In that case, the returned non-primitive value will not inherit the constructor’s prototype property.
Here’s an example:
// Define a constructor function:function CompanyProfile() { return { name: "CodeSweetly" };}
// Create an object based on the CompanyProfile() constructor:const bestWebsite = new CompanyProfile();
// Check bestWebsite's content:bestWebsite;
// The invocation above will return:{ name: "CodeSweetly";}
// Check if CompanyProfile's prototype is equivalent to bestWebsite's dunder proto:CompanyProfile.prototype === Object.getPrototypeOf(bestWebsite);
// The invocation above will return: falsebestWebsite did not inherit the CompanyProfile’s prototype property because the constructor returned its object using the return keyword.
Therefore, always omit the return keyword whenever you want your object instance to inherit its constructor’s prototype.
Here’s an example:
// Define a constructor function:function CompanyProfile() { this.name = "CodeSweetly";}
// Create an object based on the CompanyProfile() constructor:const bestWebsite = new CompanyProfile();
// Check bestWebsite's content:bestWebsite;
// The invocation above will return:{ name: "CodeSweetly";}
// Check if CompanyProfile's prototype is equivalent to bestWebsite's dunder proto:CompanyProfile.prototype === Object.getPrototypeOf(bestWebsite);
// The invocation above will return: trueThe bestWebsite object instance above inherited the CompanyProfile’s prototype property because the constructor did not use the return keyword to return its object.
2. Always use the new keyword to invoke constructors
Section titled “2. Always use the new keyword to invoke constructors”Suppose you invoke your constructor function without the new keyword. In that case, the constructor will operate like a regular function. Consequently, you may unintentionally create features in the global scope.
Here’s an example:
// Define a function:function CompanyProfile() { this.name = "CodeSweetly";}
// Invoke the CompanyProfile() constructor without using the new keyword:const bestWebsite = CompanyProfile(); // Note the "new" keyword's omission
// Check bestWebsite's name property's value:bestWebsite.name;
// The invocation above will return:// Uncaught TypeError: Cannot read properties of undefined (reading 'name')
// Check if the name property is in the global scope:window.name;
// The invocation above will return: "CodeSweetly"The window.name code returned "CodeSweetly" because the omission of the keyword new caused the constructor’s this keyword to reference the global window object.
3. Use new.target to confirm if the new operator invoked a constructor
Section titled “3. Use new.target to confirm if the new operator invoked a constructor”You can use the new.target meta-property to verify whether the new operator invoked a specified constructor.
Suppose the new operator invoked the constructor. In that case, the new.target meta-property will return a reference to the constructor. Otherwise, it returns undefined.
Here’s an example:
// Define a function:function CompanyProfile() { return new.target;}
// Invoke CompanyProfile without the new operator:CompanyProfile();
// The invocation above will return:// undefined
// Invoke CompanyProfile with the new operator:new CompanyProfile();
// The invocation above will return:ƒ CompanyProfile() { return new.target;}Therefore, you can program your code to behave as a constructor and a regular function like so:
// Define a function:function CompanyProfile() { // If CompanyProfile is a regular function run: if (!new.target) { return { name: "CodeSweetly Tutorials" }; }
// If CompanyProfile is a constructor run: this.name = "CodeSweetly Shop";}
// Invoke CompanyProfile without the new operator:CompanyProfile();
// The invocation above will return:{ name: "CodeSweetly Tutorials";}
// Invoke CompanyProfile with the new operator:new CompanyProfile();
// The invocation above will return:{ name: "CodeSweetly Shop";}