JavaScript Class Basic Syntax

Frequently it is necessary to create many objects of the same kind. As it was already noted in chapter Constructor, operator “new”, you can do it with the help of the new function.

In modern JavaScript, there exists a more advanced “class” construct, introducing new features that are useful for object-oriented programming.

The “class” Syntax

The syntax is as follows:

class MyClass {
  // class methods
  constructor() { ...
  }
  method1() { ...
  }
  method2() { ...
  }
  method3() { ...
  }
    ...
}

Then it would be best if you used new MyClass() for creating a new object including all the listed methods.

The constructor() method is automatically invoked by new. Hence, the object can be initialized there.

For instance:

class Site {
  constructor(siteName) {
    this.siteName = siteName;
  }
  welcome() {
    console.log(this.siteName);
  }
}
// Usage:
let site = new Site("W3Docs");
site.welcome();

At the time a new Site("W3Docs") is called, a new object is generated. Besides, the constructor runs with a particular argument assigning this.siteName to it.

Then you can call object methods. For example, site.welcome().

It is essential to know that you should not put a comma between class methods. It results in a syntax error.

Describing a Class

For a better understanding of many complex aspects, it’s necessary to learn what a class is.

So, a JavaScript class is a kind of function.

For instance:

class Site {
  constructor(siteName) {
    this.siteName = siteName;
  }
  welcome() {
    console.log(this.siteName);
  }
}
// proof: Site is a function
console.log(typeof Site); // function

The class Site {...} construct operates as follows:

  • It generates a function, known as Site, which becomes the result of the class declaration. The function code is derived from the constructor method.
  • It stocks class methods (welcome, in Site.prototype).

Following the creation of the new Site object, it is taken from the prototype. It means that the object has access to class methods.

The code looks like this:

class Site {
  constructor(siteName) {
    this.siteName = siteName;
  }
  welcome() {
    console.log(this.siteName);
  }
}
// class is a function
console.log(typeof Site); // function
// ...or, more precisely, the constructor method
console.log(Site === Site.prototype.constructor); // true
// The methods are in Site.prototype, e.g:
console.log(Site.prototype.welcome); // cosnole.log(this.siteName);
// there are exactly two methods in the prototype
console.log(Object.getOwnPropertyNames(Site.prototype)); // constructor, welcome

More Than a “syntactic sugar”

Often the class is compared to “syntactic sugar” (a syntax that is aimed at making things easy-readable not introducing anything new) as it is possible to declare the same without using the class keyword.

Take a look at this example:

// rewriting class Site in pure functions
// 1. Create constructor function
function Site(siteName) {
  this.siteName = siteName;
}
// any function prototype has constructor property by default,
// so we don't need to create it

// 2. Add the method to prototype
Site.prototype.welcome = function () {
  console.log(this.siteName);
};
// Usage:
let site = new Site("W3Docs");
site.welcome();

But there exist notable differences:

  1. First of all, a function that class creates is stamped by a unique internal property, such as [[FunctionKind]]:"classConstructor".

    In contrast with a regular function, a class constructor should be called with new:

    class Site {
      constructor() {}
    }
    console.log(typeof Site); // function
    Site(); // Error: Class constructor Site cannot be invoked without 'new'
  2. The class methods are considered non-enumerable. The definition of the class sets enumerable flag to false overall methods in the "prototype".

    Note that in case you for..in over an object, commonly you don’t want the class methods.

  3. The use strict is always used by the classes. So, the code inside the class construct is by default in strict mode.

Class Expression

Classes are like functions: they can be defined inside another expression, assigned, passed around, returned, and more.

is a class expression example:

let Site = class {
  welcome() {
    console.log("W3Docs");
  }
};

Class expression can have a name. But its name is visible only inside the class.

For instance:

// "Named Class Expression"
// that's similar to Named Function Expression, but no such term in the spec
let Site = class MyClass {
  welcome() {
    console.log(MyClass); // MyClass name is visible only inside the class
  }
};

new Site().welcome(); // works, shows MyClass definition
console.log(MyClass); // error, MyClass name isn't visible outside of the class

You even have the option of making “on-demand” classes, as follows:

function createClass(message) {
  // declare a class and return it
  return class {
    welcome() {
      console.log(message);
    };
  };
}
// Create a new class
let Site = createClass("Welcome to W3Docs");
new Site().welcome(); // Welcome to W3Docs

Shorthands

Like literal objects, classes can include shorthands, such as getter/setters, computer properties, and more.

In this example, the getter/setter is used:

class Site {
  constructor(siteName) {
    // invokes the setter
    this.siteName = siteName;
  }
  get siteName() {
    return this._siteName;
  }
  set siteName(value) {
    if (value.length < 3) {
      console.log("Site name is too short.");
      return;
    }
    this._siteName = value;
  }
}
let site = new Site("W3Docs");
console.log(site.siteName); // W3Docs
site = new Site(""); // Site name is too short.

The class declaration generates getters and setters inside Site.prototype, as follows:

Object.defineProperties(Site.prototype, {
  siteName: {
    get() {
      return this._siteName
    },
    set(siteName) {
      // ...
    }
  }
});

Another example includes computed property name in brackets [...]:

class Site {
  ['say' + 'Welcome']() {
    console.log("Welcome to W3Docs");
  }
}
new Site().sayWelcome();

Class Properties

Let’s try to add a property to the example above:

class Site {
  siteName = "W3Docs";
  welcome() {
    console.log(`Welcome to ${this.siteName}!`);
  }
}
new Site().welcome();
console.log(Site.prototype.welcome); // placed in Site.prototype
console.log(Site.prototype.siteName); // undefined, not placed in Site.prototype

The name of the property is not placed into Site.prototype. It is generated by new before running the constructor. It’s a property of the object.




Do you find this helpful?

Related articles