What is the ‘new’ keyword in JavaScript and how does it work?
The ‘new’ keyword in JavaScript can be confusing for beginners, especially for those who mistakenly believe JavaScript isn’t an object-oriented programming language. This comprehensive guide aims to clarify:
- What exactly is the ‘new’ keyword in JavaScript?
- What problems does the ‘new’ keyword solve in JavaScript development?
- When is it appropriate to use the ‘new’ keyword, and when should it be avoided?
- How does the ‘new’ keyword affect object creation and inheritance in JavaScript?
- What are the best practices for using the ‘new’ keyword in modern JavaScript development?
The ‘new’ keyword in JavaScript is an operator that creates a new object and invokes a constructor function, automatically binding the ‘this’ keyword to the newly created object and establishing prototype-based inheritance. When used with a function, ‘new’ transforms that function into a constructor, creating an instance that inherits properties and methods from the constructor’s prototype, while allowing each instance to have its own set of properties based on the constructor’s initialization logic.
Contents
- What Exactly Is the ‘new’ Keyword in JavaScript?
- How the ‘new’ Keyword Works: Step by Step
- Problems the ‘new’ Keyword Solves
- When to Use the ‘new’ Keyword
- When to Avoid the ‘new’ Keyword
- Modern Alternatives and Best Practices
What Exactly Is the ‘new’ Keyword in JavaScript?
The ‘new’ keyword is a JavaScript operator that creates an instance of an object. Technically, any function (except arrow functions, which don’t have their own ‘this’) can be used as a constructor when called with ‘new’. The common convention in JavaScript is to capitalize the first letter of constructor functions to indicate they should be called with ‘new’, making it clear that a function is intended to be used as a constructor source.
When we use ‘new’, we’re essentially telling JavaScript to treat the following function as a constructor rather than a regular function call. This distinction is crucial because it changes how JavaScript handles the function execution and object creation process.
function Person(name, age) {
this.name = name;
this.age = age;
}
const person1 = new Person('Alice', 30);
const person2 = new Person('Bob', 25);
In this example, ‘Person’ is a constructor function that, when called with ‘new’, creates new instances with their own ‘name’ and ‘age’ properties.
How the ‘new’ Keyword Works: Step by Step
When you use the ‘new’ keyword with a function, JavaScript performs a multi-step process behind the scenes:
-
Creates an empty object: The ‘new’ keyword creates an entirely new, empty object source.
-
Sets up prototype linkage: The new object is linked to the constructor function’s prototype property, establishing inheritance source.
-
Binds ‘this’ to the new object: Inside the constructor function, the ‘this’ keyword now refers to the newly created object, not the global object source.
-
Executes the constructor function: JavaScript runs the constructor function with the provided arguments, allowing you to initialize the new object’s properties.
-
Returns the new object: If no explicit return statement is provided, the new object is automatically returned source.
Here’s a visual representation of what happens when calling new Person('Alice', 30):
// Behind the scenes, JavaScript does something like this:
const person = {
__proto__: Person.prototype
};
Person.call(person, 'Alice', 30);
return person;
This process ensures that each new instance maintains its own properties while sharing methods and other properties from the prototype chain.
Problems the ‘new’ Keyword Solves
The ‘new’ keyword addresses several fundamental challenges in JavaScript object-oriented programming:
Proper ‘this’ Binding
Without ‘new’, calling a constructor function would result in ‘this’ referring to the global object (or undefined in strict mode), potentially polluting the global namespace or causing errors. The ‘new’ keyword ensures that ‘this’ correctly refers to the newly created object source.
Prototype-Based Inheritance
JavaScript uses prototypal inheritance rather than classical inheritance. The ‘new’ keyword automatically sets up the prototype chain, allowing instances to inherit properties and methods from the constructor’s prototype source.
Object Creation and Initialization
Before ‘new’, creating multiple similar objects required repetitive code. The ‘new’ keyword provides a structured way to create and initialize multiple instances of the same object type with consistent behavior.
Memory Efficiency
By sharing methods through the prototype rather than duplicating them on each instance, the ‘new’ keyword helps create more memory-efficient code.
When to Use the ‘new’ Keyword
Creating Multiple Similar Objects
When you need to create multiple objects that share common properties and methods, constructor functions with ‘new’ provide an efficient solution:
function Product(name, price) {
this.name = name;
this.price = price;
}
Product.prototype.display = function() {
console.log(`${this.name}: $${this.price}`);
};
const laptop = new Product('Laptop', 999);
const phone = new Product('Phone', 699);
Establishing Inheritance Hierarchies
The ‘new’ keyword is essential for creating inheritance chains in JavaScript:
function Animal(name) {
this.name = name;
}
Animal.prototype.speak = function() {
console.log(`${this.name} makes a sound`);
};
function Dog(name, breed) {
Animal.call(this, name); // Call parent constructor
this.breed = breed;
}
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
const myDog = new Dog('Rex', 'German Shepherd');
Maintaining Clean Code Structure
Using ‘new’ with constructor functions helps organize code by clearly separating object creation from object behavior, making the code more readable and maintainable.
When to Avoid the ‘new’ Keyword
Arrow Functions
Arrow functions cannot be used as constructors because they don’t have their own ‘this’ context. Attempting to use ‘new’ with an arrow function will throw an error:
const ArrowConstructor = () => {};
const instance = new ArrowConstructor(); // TypeError: ArrowConstructor is not a constructor
Functions Not Designed as Constructors
Using ‘new’ with regular functions that aren’t designed as constructors can lead to unexpected behavior:
function add(a, b) {
return a + b;
}
const result = new add(2, 3); // Returns an empty object, not 5
Modern JavaScript with ES6 Classes
While ‘new’ still works with ES6 classes, many developers prefer the cleaner syntax:
// Instead of:
function Car(make, model) {
this.make = make;
this.model = model;
}
Car.prototype.start = function() {
console.log('Engine started');
};
// Use:
class Car {
constructor(make, model) {
this.make = make;
this.model = model;
}
start() {
console.log('Engine started');
}
}
Modern Alternatives and Best Practices
ES6 Classes
The modern approach to object creation in JavaScript is using ES6 classes, which provide syntactic sugar over the prototype-based inheritance model:
class Person {
constructor(name, age) {
this.name = name;
this.age = age;
}
greet() {
return `Hello, my name is ${this.name}`;
}
}
const person = new Person('Alice', 30);
As one developer notes, “Using the class keyword is absolutely compatible with current best practices” source.
Object Composition
Instead of relying on inheritance, many modern JavaScript developers prefer object composition:
const canEat = {
eat() {
console.log('Eating...');
}
};
const canSleep = {
sleep() {
console.log('Sleeping...');
}
};
const person = {
...canEat,
...canSleep,
name: 'Alice'
};
Factory Functions
Factory functions provide an alternative to constructor functions with ‘new’:
function createPerson(name, age) {
return {
name,
age,
greet() {
return `Hello, my name is ${this.name}`;
}
};
}
const person = createPerson('Alice', 30);
Module Pattern
The module pattern offers encapsulation without requiring ‘new’:
const personModule = (function() {
let name;
let age;
return {
setName(n) {
name = n;
},
setAge(a) {
age = a;
},
getInfo() {
return { name, age };
}
};
})();
Best Practices Summary
-
Use ES6 classes for new code: They provide a cleaner syntax while maintaining the same prototype-based inheritance under the hood source.
-
Consider alternatives to classes: Some experienced developers argue that “JavaScript is awesome enough to offer far better alternatives, such as object composition and prototypal inheritance” source.
-
Be consistent: Whatever approach you choose, use it consistently throughout your codebase.
-
Understand the underlying mechanisms: Even when using modern syntax, understanding how ‘new’ and prototypes work will make you a better JavaScript developer.
Conclusion
The ‘new’ keyword in JavaScript is a powerful operator that creates objects and establishes prototype-based inheritance, but it’s not always the best choice for modern JavaScript development. Key takeaways include:
- The ‘new’ keyword creates an object, binds ‘this’ to that object, sets up prototype inheritance, and returns the new instance
- While essential for understanding JavaScript’s object model, many developers now prefer ES6 classes as the modern standard
- Object composition, factory functions, and the module pattern offer alternatives to traditional constructor functions
- The best approach depends on your specific needs, team preferences, and the complexity of your application
Whether you’re working with legacy code or starting fresh, understanding how ‘new’ works will help you make informed decisions about object creation and inheritance in JavaScript.
Sources
- JavaScript.info - Constructor, operator “new”
- MDN - new operator
- DigitalOcean - Understanding Prototypes and Inheritance in JavaScript
- Stack Overflow - What is the ‘new’ keyword in JavaScript?
- Mbloging - Understanding the new keyword in JavaScript
- Stack Overflow - JavaScript Object creation with the ‘new’ keyword
- Reddit - Using Classes in Javascript (ES6) — Best practice?
- Stack Overflow - Is JavaScript’s “new” keyword considered harmful?
- GitHub - We are better off avoiding ES6 classes in JavaScript when possible
- Medium - JavaScript’s new keyword, under the hood