More from this author

JavaScript object creation is a tricky subject. The language 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. In this article, I’m going to take you on a tour of the various styles of object creation and how each builds on the others in incremental steps.

Object Literals

The first stop on our tour is the absolute simplest way to create objects, 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 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.

But there’s a drawback. This approach 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.

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.

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.

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”.

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 withclosures and classes withweak maps. Both can achieve multiple inheritance—factory functions by mixing other properties into its own object, and classes also by mixing other properties into its 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 is for 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.