In this article, I’m going to take you on a tour of the various styles of JavaScript object creation, and how each builds on the others in incremental steps.
JavaScript has a multitude of styles for creating objects, and newcomers and veterans alike can feel overwhelmed by the choices and unsure which they should use. But despite the variety and how different the syntax for each may look, they’re more similar than you probably realize.
Object Literals
The first stop on our tour is the absolute simplest method of JavaScript object creation — the object literal. JavaScript touts that objects can be created “ex nilo”, out of nothing — no class, no template, no prototype — just poof!, an object with methods and data:
var o = {
x: 42,
y: 3.14,
f: function() {},
g: function() {}
};
But there’s a drawback. If we need to create the same type of object in other places, then we’ll end up copy-pasting the object’s methods, data, and initialization. We need a way to create not just the one object, but a family of objects.
Factory Functions
The next stop on our JavaScript object creation tour is the factory function. This is the absolute simplest way to create a family of objects that share the same structure, interface, and implementation. Rather than creating an object literal directly, instead we return an object literal from a function. This way, if we need to create the same type of object multiple times or in multiple places, we only need to invoke a function:
function thing() {
return {
x: 42,
y: 3.14,
f: function() {},
g: function() {}
};
}
var o = thing();
But there’s a drawback. This approach of JavaScript object creation can cause memory bloat, because each object contains its own unique copy of each function. Ideally, we want every object to share just one copy of its functions.
Prototype Chains
JavaScript gives us a built-in mechanism to share data across objects, called the prototype chain. When we access a property on an object, it can fulfill that request by delegating to some other object. We can use that and change our factory function so that each object it creates contains only the data unique to that particular object, and delegate all other property requests to a single, shared object:
var thingPrototype = {
f: function() {},
g: function() {}
};
function thing() {
var o = Object.create(thingPrototype);
o.x = 42;
o.y = 3.14;
return o;
}
var o = thing();
In fact, this is such a common pattern that the language has built-in support for it. We don’t need to create our own shared object (the prototype object). Instead, a prototype object is created for us automatically alongside every function, and we can put our shared data there:
thing.prototype.f = function() {};
thing.prototype.g = function() {};
function thing() {
var o = Object.create(thing.prototype);
o.x = 42;
o.y = 3.14;
return o;
}
var o = thing();
But there’s a drawback. This is going to result in some repetition. The first and last lines of the thing
function are going to be repeated almost verbatim in every such delegating-to-prototype factory function.
ES5 Classes
We can isolate the repetitive lines by moving them into their own function. This function would create an object that delegates to some other arbitrary function’s prototype, then invoke that function with the newly created object as an argument, and finally return the object:
function create(fn) {
var o = Object.create(fn.prototype);
fn.call(o);
return o;
}
// ...
Thing.prototype.f = function() {};
Thing.prototype.g = function() {};
function Thing() {
this.x = 42;
this.y = 3.14;
}
var o = create(Thing);
In fact, this too is such a common pattern that the language has some built-in support for it. The create
function we defined is actually a rudimentary version of the new
keyword, and we can drop-in replace create
with new
:
Thing.prototype.f = function() {};
Thing.prototype.g = function() {};
function Thing() {
this.x = 42;
this.y = 3.14;
}
var o = new Thing();
We’ve now arrived at what we commonly call “ES5 classes”. They’re object creation functions that delegate shared data to a prototype object and rely on the new
keyword to handle repetitive logic.
But there’s a drawback. It’s verbose and ugly, and implementing inheritance is even more verbose and ugly.
ES6 Classes
A relatively recent addition to JavaScript is ES6 classes, which offer a significantly cleaner syntax for doing the same thing:
class Thing {
constructor() {
this.x = 42;
this.y = 3.14;
}
f() {}
g() {}
}
const o = new Thing();
Comparison
Over the years, we JavaScripters have had an on-and-off relationship with the prototype chain, and today the two most common styles you’re likely to encounter are the class syntax, which relies heavily on the prototype chain, and the factory function syntax, which typically doesn’t rely on the prototype chain at all. The two styles differ — but only slightly — in performance and features.
Performance
JavaScript engines are so heavily optimized today that it’s nearly impossible to look at our code and reason about what will be faster. Measurement is crucial. Yet sometimes even measurement can fail us. Typically, an updated JavaScript engine is released every six weeks, sometimes with significant changes in performance, and any measurements we had previously taken, and any decisions we made based on those measurements, go right out the window. So, my rule of thumb has been to favor the most official and most widely used syntax, under the presumption that it will receive the most scrutiny and be the most performant most of the time. Right now, that’s the class syntax, and as I write this, the class syntax is roughly 3x faster than a factory function returning a literal.
Features
What few feature differences there were between classes and factory functions evaporated with ES6. Today, both factory functions and classes can enforce truly private data—factory functions with closures and classes with weak maps. Both can achieve multiple-inheritance factory functions by mixing other properties into their own object, and classes also by mixing other properties into their prototype, or with class factories, or with proxies. Both factory functions and classes can return any arbitrary object if need be. And both offer a simple syntax.
Conclusion
All things considered, my preference for JavaScript object creation is to use the class syntax. It’s standard, it’s simple and clean, it’s fast, and it provides every feature that once upon a time only factories could deliver.
This article was peer reviewed by Tim Severien and Sebastian Seitz. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!
Frequently Asked Questions (FAQs) about JavaScript Object Creation Patterns and Best Practices
What are the different ways to create objects in JavaScript?
There are several ways to create objects in JavaScript. The simplest way is to use the object literal syntax, which involves defining an object within curly braces {}. Another way is to use the ‘new’ keyword followed by the Object() constructor. You can also use the Object.create() method, which creates a new object with the specified prototype object and properties. Lastly, you can use a function constructor, which is a regular function used to construct objects.
How does the ‘new’ keyword work in JavaScript?
The ‘new’ keyword in JavaScript is used to create an instance of a user-defined object type or of one of the built-in object types. When used, it creates a new empty object, and then calls the function specified, with ‘this’ set to the new object. The properties and methods inside the function become part of the new object.
What is the difference between Object.create() and the ‘new’ keyword?
The main difference between Object.create() and the ‘new’ keyword is that Object.create() allows you to directly specify the prototype of the object you’re creating, while the ‘new’ keyword creates a new object from a constructor function, and its prototype is set to the function’s prototype property.
How do I add properties to an object in JavaScript?
You can add properties to an object in JavaScript in several ways. One way is to use dot notation, where you specify the object, followed by a dot, followed by the property name. Another way is to use bracket notation, where you specify the object, followed by the property name in brackets. You can also add properties when you create the object, by including them in the object literal or constructor function.
What is a constructor function in JavaScript?
A constructor function in JavaScript is a special type of function that is used to create objects. It is called with the ‘new’ keyword, and it returns a new object. The name of a constructor function usually starts with a capital letter to distinguish it from regular functions.
How do I create a method in an object?
To create a method in an object, you define a function within the object. This can be done within the object literal, or by adding the function to the object after it has been created using dot notation or bracket notation. The function can then be called as a method of the object.
What is prototypal inheritance in JavaScript?
Prototypal inheritance is a type of inheritance in JavaScript where objects inherit properties and methods from a prototype object. This is different from classical inheritance, where objects inherit from a class. In JavaScript, every object has a prototype, and the prototype of an object created with a constructor function is the prototype property of that function.
How do I use the ‘this’ keyword in JavaScript?
The ‘this’ keyword in JavaScript is used to refer to the object that the function is a method of. It is automatically set by JavaScript when a function is called, and its value depends on how the function was called. In a method, ‘this’ refers to the owner object. In a function, ‘this’ refers to the global object.
What is the difference between a method and a function in JavaScript?
The main difference between a method and a function in JavaScript is that a method is a function that is a property of an object. When a function is called as a method of an object, the ‘this’ keyword in the function refers to the object. A function that is not a property of an object is simply called a function, and the ‘this’ keyword in the function refers to the global object.
How do I create a private property in an object?
In JavaScript, you can create a private property in an object by defining a variable within the constructor function. This variable is only accessible within the function, and it is not accessible from outside the function or from methods of the object. To access the private property, you can define a public method within the constructor function that returns the value of the private property.
Jeff has been doing frontend and backend Web development since '98 when Perl and floppy disks were a thing. Later he worked in PHP and Symfony with an agency in San Francisco. In 2009, he joined Intel and often works with NodeWebkit, Angular, C++, Python, and much more.