JS: Define Class

By Xah Lee. Date: . Last updated: .

(new in ECMAScript 2015)

defining properties, and private variable and private method, are new in ECMAScript 2022

What is keyword “class”

the keyword class lets you define a Constructor.

Class syntax

The syntax for class declaration is:

class ClassName {body}

in body, you can have optional:

constructor (params) {body}

Constructor is a function. It is called when new ClassName() is called.

Instance members

in the class body, you can have any of (all optional):

Instance variables become the properties of the object created by the constructor. Each instance has its own copy.

Instance methods become properties of the instance's parent object.

and you can also define getter setter properties.

Static members

Any property name or method can also be declared with keyword static. Static means they become properties of the constructor object.

Private members

Private members are names that start with hash #. Private members mean they are only visible within the class body. Getters and setters can also be private.

static members can also be private.

Example. basic burger class

// example of a class
class Burger {
 constructor(x) {
  this.meat = x;
  console.log("constructor called with arg " + x);
 }

 static bread = 2;

 static add_bread(x) {
  console.log("add_bread called with arg " + x);
  Burger.bread = Burger.bread + x;
 }

 cheese = 1;

 add_cheese(x) {
  console.log("add_cheese called with arg " + x);
  this.cheese = this.cheese + x;
 }
}

// s------------------------------
// test the class constructor

// static variable is property of the constructor
console.log(Burger.bread);
// 2

// static method is property of the constructor
Burger.add_bread(1);
// add_bread called with arg 1

console.log(Burger.bread);
// 3

// s------------------------------
// create a instance

const my_burger = new Burger(1);
// constructor called with arg 1

console.log(my_burger);
// Burger { cheese: 1, meat: 1 }

my_burger.add_cheese(99);
// add_cheese called with arg 99

console.log(my_burger);
// Burger { cheese: 100, meat: 1 }

// s------------------------------
// create another instance

const x_burger = new Burger(1);
// constructor called with arg 1

console.log(x_burger);
// Burger { cheese: 1, meat: 1 }

Constructor

constructor (param) {body}
  • This defines the Constructor function.
  • This function is automatically called when new ClassName is called.
  • There can be only one constructor, and is optional. Default constructor does nothing.

when the constructor is called:

  1. A new temporary empty data object TempObj is created. Parent of TempObj is MyClass.prototype.
  2. In the constructor body, the this-binding is TempObj.
  3. If the constructor method has return statement and returns a value of Object Type, then that object is returned. Else, TempObj is returned.

🟢 tip: typically, don't use return statement in constructor.

// example of a class

class Pizza {
 constructor(x) {
  this.meat = x;
  console.log("constructor called with arg " + x);
 }
}

// s------------------------------

// create a instance
const xpizza = new Pizza("beef");
// constructor called with arg beef

console.log(xpizza);
// Pizza { meat: "beef" }

Instance properties and methods

Instance fields

when you have

These are called instance fields or instance properties or instance variables .

Instance fields become the properties of the object created by the constructor. Each instance has its own copy.

Value can be any JavaScript value, including data object or function.

Instance methods

Instance methods become properties of the instance's parent object.

Verify instance members behavior

// verify instance member behavior of a class
class Burger {
 constructor(x) {
  this.meat = x;
 }

 cheese = 1;

 add_cheese(x) {
  this.cheese = this.cheese + x;
 }
}

// s------------------------------

// create a instance
const my_burger = new Burger(1);

// all instance VARIABLES are own properties of the created object

console.assert(
 Object.hasOwn(my_burger, "meat"),
 Object.hasOwn(my_burger, "cheese"),
);

// parent is Burger.prototype
console.assert(
 Reflect.getPrototypeOf(my_burger) === Burger.prototype,
);

// all instance METHODS are own properties of the parent object
console.assert(
 Object.hasOwn(Burger.prototype, "add_cheese"),
);

Instance field with value of function

🛑 warning: if instance field's value is a function, it overrides instance method of the same name. Because it is the instance's own property, while the method is property of its parent.

class CCC {
 // this is instance field. value is a function
 add1 = ((x) => {
  console.log("instance field's value function called");
  return x + 1;
 });

 // this is instance method.
 add1(x) {
  console.log("instance method called");
  return x + 1;
 }
}

const jj = new CCC();

console.assert(Object.hasOwn(jj, "add1"));
console.assert(Object.hasOwn(CCC.prototype, "add1"));
console.assert(Reflect.getPrototypeOf(jj) === CCC.prototype);

console.log(jj.add1(1));
// instance field's value function called
// 2

console.log(CCC.prototype.add1(1));
// instance method called
// 2

Static members

Private fields and methods

Class must be defined before call (no name hoisting)

Class declaration must come before the class is called. (i.e. Class name is not hoisted.)

// class must be defined before call

const xx = new MyClass();
// error: Uncaught ReferenceError: Cannot access 'MyClass' before initialization

class MyClass {}

Class must be called with “new”

Class function must be called with keyword new. It cannot be called like a function by itself.

class MyClass {}
MyClass();
// error: Uncaught TypeError: Class constructor MyClass cannot be invoked without 'new'

Example. class getter property

class Pig {
 // getter property
 get gg() {
  return 3;
 }
}

const xx = new Pig();
console.assert(xx.gg === 3);

Class name start with capitalized letter

This is by convention.