Our content is free thanks to ag-Grid

ag-Grid is the industry leading JavaScript datagrid

ag-grid.com

Getting Started with Modern JavaScript — Classes

Post Editor

We often need to create many objects of the same kind, like users or cars. In object-oriented languages, a class is often used for this purpose.JavaScript, being a prototype-based language, has something called constructor functions.

4 min read
post

Getting Started with Modern JavaScript — Classes

We often need to create many objects of the same kind, like users or cars. In object-oriented languages, a class is often used for this purpose.JavaScript, being a prototype-based language, has something called constructor functions.

post
post
4 min read
4 min read

We often need to create many objects of the same kind, like users or cars. In object-oriented languages, a class is often used for this purpose.
JavaScript, being a prototype-based language, has something called constructor functions.

// ES5 constructor function
function Car(brand) {
  this.brand = brand;
}

// Adding a method to the prototype
Car.prototype.getBrand = function() {
  return this.brand;
}

Classes, introduced with ES6 provide “syntactical sugar”, that is comparable to inheritance in object-oriented languages. Classes are special functions meant to mimic the class keyword from these other languages. In this article we go through how to use JavaScript classes.

Defining a Class

To define a class we use the class keyword followed by the name of the class. The body of a class is the part that is in curly braces {}:

class Car {
  // Body of the class
}

The code above defines a class Car. This syntax is named class declaration.

The new operator instantiates the class:

const myCar = new Car();

This is how we create a new object, an instance, of the Car class.

console.log(typeof Car); // -> function

And as you can see, in JavaScript, a class is a kind of function.

We don’t need to give the class a name. By using a class expression you can assign the class to a variable:

const Car = class {} // unnamed
const Car = class Car {} // named

Class expressions can be named or unnamed. The name given to a named class expression is local to the class’s body.

Hoisting

An important difference between function declarations and class declarations is that function declarations are hoisted and class declarations are not. Therefore you need to first declare the class before you can initialize objects with the new keyword.

Conceptually, for example, a strict definition of hoisting suggests that variable and function declarations are physically moved to the top of your code, but this is not in fact what happens. Instead, the variable and function declarations are put into memory during the compile phase, but stay exactly where you typed them in your code. — MDN

As you might remember variables declared with var are also hoisted. So, keeping with the “modern” way it makes then sense that classes just like variables declared with let or const are not hoisted.

Initialization

Classes in JavaScript have a special method called constructor that lets us set initial values for fields when the object is initialized. There can be only one constructor method.

Let’s create a Car class with a constructor that sets the initial value of the field brand:

class Car {
  constructor(brand) {
    this.brand = brand; 
  } 
}

The expression this.brand = brand creates a public field brand and assigns it an initial value. We can now create a new car object and access it’s brand property:

const car = new Car('Volvo');
console.log(car.brand); // -> Volvo

As you can see we can now access the brand field using a property accessor. There’s no restriction on the access of the public fields. You can read and modify the values of public fields inside the constructor, methods, and outside of the class.

The bodies of class declarations and class expressions are executed in strict mode.

Methods

Classes provide a cleaner and more elegant syntax for adding methods.

class Car { 
  constructor(brand) {
    this.brand = brand;
  } 
 
  getBrand() {
    return this.brand;
  }
}

The keyword this allows us to access instance data inside the constructor and methods.

const car = new Car('Tesla');
console.log(car.getBrand()); // -> Tesla

The method invocation car.getBrand() executes the methods inside the Car class and returns the brand property.

Static Methods

We can also assign a method to the class function itself, not to its prototype. Such methods are called static and are prepended with the static keyword:

class Double {
  static double(n) {
    return n * 2;
  }
}

Double.double(2); // -> 4

We don’t have to create an instance of the class but can call the method directly on the class itself. Static methods are often used in utility classes for making computations.

Getters and Setters

JavaScript classes can have getter and setter functions.

class Car { 
  constructor(brand) {
    this._brand = brand;
  }

  get brand() {
    return this._brand;
  }

  set brand(value) {
    this._brand = value;
  }
}

Notice that if you would do this.brand = value in the setter we would be calling the setter again and go into an infinite loop. Using an underscore _ is a common convention.

With this we can create an instance of the class and access the brand property through the setter and getter:

const car = new Car('');
car.brand = 'Tesla;
console.log(car.brand); // -> Tesla

Inheritance

Class inheritance is a way to inherit the functionality of another class and extend it. We create a child class with the extends keyword.

class SportsCar extends Car {
  isFast() {
    return true;
  }
}

Now we can use the functionality of the class we extended:

const car = new SportsCar('Mazda');
console.log(car.brand); // -> Mazda
console.log(car.isFast()); // -> true

You can see here that we didn’t have to create a constructor. If a class extends another class and has no constructor, then the following constructor is generated:

constructor(...args) {
  super(...args); // Copying args with spread operator (...)
}

The super keyword is used to call corresponding methods of the parent class. So the constructor calls the parent constructor passing it all the arguments. If we want to add another in-parameter to our class we can create a constructor:

class SportsCar extends Car {
  constructor(brand, model) {
    super(brand);
    this.model = model;
  }
}

const myCar = new SportsCar('Mazda', 'MX-5');

Note that constructors in inheriting classes must call super(), and do it before using this.

Conclusion

  • Use classes when you need to create multiple objects of the same kind.
  • Classes are a special kind of functions that run in strict mode and are not hoisted.
  • Classes can have fields and methods that we can access from a class instance.
  • We can inherit functionality from other classes by extending them.
Discuss with community

Share

About the author

author_image
Michael Karén

Angular by day. React by night. Full-stack when needed. I like blogging about web stuff. Co-organizer ngVikings.

author_image

About the author

Michael Karén

Angular by day. React by night. Full-stack when needed. I like blogging about web stuff. Co-organizer ngVikings.

About the author

author_image
Michael Karén

Angular by day. React by night. Full-stack when needed. I like blogging about web stuff. Co-organizer ngVikings.

NxAngularCli
NxAngularCli
NxAngularCli

Featured articles

Angularpost
14 January 20216 min read
Demystifying Taiga UI root component: portals pattern in Angular

Just before new year we announced our new Angular UI kit library Taiga UI. If you go through Getting started steps, you will see that you need to wrap your app with the tui-root component. Let's see what it does and explore what portals are and how and why we use them.

JavaScriptpost
22 December 20203 min read
throwError is not throw error

The American poet Edward Estlin Cummings was famous for his eccentric use of spacing and capitalization, to the point that his name is usually styled as e e cummings. I wonder what he would think of an RxJS question that a friend asked me: “Is returning throwError the same as writing ‘throw error’?”

JavaScriptpost
22 December 20203 min read
throwError is not throw error

The American poet Edward Estlin Cummings was famous for his eccentric use of spacing and capitalization, to the point that his name is usually styled as e e cummings. I wonder what he would think of an RxJS question that a friend asked me: “Is returning throwError the same as writing ‘throw error’?”

Read more
JavaScriptpostthrowError is not throw error

22 December 2020

3 min read

The American poet Edward Estlin Cummings was famous for his eccentric use of spacing and capitalization, to the point that his name is usually styled as e e cummings. I wonder what he would think of an RxJS question that a friend asked me: “Is returning throwError the same as writing ‘throw error’?”

Read more