Define and use classes

The concept of a class is fundamental in object-oriented (OO) programming. Objects instantiate and are classified by a class. A class defines the properties and methods of the objects created with it.

A class concept is essential to implement a data model in the form of model classes in an MVC architecture. However, classes, their inheritance, and extension mechanisms are overused in classical OO languages such as Java where all variables and procedures have to be defined in the context of a class. Consequently, classes are not only used for implementing object types or model classes, but also as containers for many other purposes in these languages. This is not the case in JavaScript where we have the freedom to use classes for only implementing object types while keeping method libraries in namespace objects.

Any code pattern for defining classes in JavaScript should satisfy five requirements. These requirements are as follows:

  • It should allow class names to be defined, a set of instance-level properties (preferably with the option to keep them ‘private’), a set of instance-level methods, as well as a set of class-level properties and methods. It’s desirable that properties can be defined with a range and type, and that they can be defined with other meta-data, like constraints.
  • An is-instance-of predicate that can be used for checking if an object is a direct or indirect instance of a class.
  • An instance-level property for retrieving the direct type of an object. In addition, it is desirable to have a third introspection feature for retrieving the direct supertype of a class.
  • A property inheritance is required.
  • The definition should allow for method inheritance.

In addition, it’s a good idea to have support for multiple inheritance and multiple classifications so that objects can play several roles at the same time by instantiating several role classes.

Before ES6 (or, as it used to be known, ES2015), there was no explicit class definition syntax in JavaScript. Different code patterns to define classes in JS have been proposed and are being used in different frameworks, but they often don’t satisfy the five requirements listed above. The two most important approaches for defining classes are as follows:

  1. A constructor function achieves method inheritance through the prototype chain and allows us to create new instances of a class with the help of the new operator. This is the classical approach recommended by Mozilla in their JavaScript Guide. This is also the approach implemented in ES6 with the new class definition syntax.

  2. A factory object uses the predefined Object.create method to create new instances of a class. In this approach, the inheritance mechanism, which usually uses the prototype chain method in JavaScript, is replaced by a copy-and-append mechanism. JavaScript teacher and tech author Eric Elliott has argued that factory-based classes are a viable alternative to constructor-based classes.

When building an application, we can use both kinds of classes, depending on the requirements of the application. Since we often need to define class hierarchies and not just single classes, we have to make sure that we don’t mix these two alternative approaches within the same class hierarchy. While the factory-based approach, as exemplified by the mODELcLASSjs library, has many advantages, the constructor-based approach enjoys the advantage of higher performance object creation.

Get hands-on with 1200+ tech skills courses.