Overview

In ES6, class (class) is introduced as a template for objects, and classes can be defined using the class keyword.

The essence of class is function.

It can be seen as syntactic sugar, making the object prototype syntax clearer and more like object-oriented programming syntax.

Basic Usage

Class Definition

Class expressions can be anonymous or named.

//Anonymous class let Example = class { constructor(a) { this.a = a; } } //Named class let Example = class Example { constructor(a) { this.a = a; } }

Class Declaration

class Example { constructor(a) { this.a = a; } }

Important note: cannot be redeclared.

class Example{} class Example{} // Uncaught SyntaxError: Identifier 'Example' has already been // declared let Example1 = class{} class Example{} // Uncaught SyntaxError: Identifier 'Example' has already been // declared

Important Notes

Class definitions are not hoisted, meaning you must define a class before accessing it, otherwise an error will be thrown.

Methods in a class do not require the function keyword.

Semicolons cannot be added between methods.

new Example(); class Example {}

Class Body

Properties

prototype

In ES6, prototype still exists. Although methods can be defined directly in the class, they are actually still defined on prototype. Override methods / Add methods during initialization

Example.prototype={ //methods }

Add methods

Object.assign(Example.prototype,{ //methods })

Static properties

Static properties: properties of the class itself, i.e., properties directly defined inside the class (Class.propname), which do not require instantiation. In ES6, it is specified that Class only has static methods, not static properties.

class Example { //New proposal static a = 2; } //Currently feasible approach Example.b = 2;

Public properties

class Example{} Example.prototype.a = 2;

Instance properties

Instance properties: properties defined on the instance object (this).

class Example { a = 2; constructor () { console.log(this.a); } }

name property

Returns the class name following class (if present).

let Example=class Exam { constructor(a) { this.a = a; } } console.log(Example.name); // Exam let Example=class { constructor(a) { this.a = a; } } console.log(Example.name); // Example

Methods

constructor method

The constructor method is the default method of a class and is called when creating an instance object of the class.

class Example{ constructor(){ console.log('I am constructor'); } } new Example(); //I am constructor

Return object

class Test { constructor(){ //Returns the instance object this by default } } console.log(new Test() instanceof Test); // true class Example { constructor(){ //Specify return object return new Test(); } } console.log(new Example() instanceof Example); // false

Static methods

class Example{ static sum(a, b) { console.log(a+b); } } Example.sum(1, 2); // 3

Prototype methods

class Example { sum(a, b) { console.log(a + b); } } let exam = new Example(); exam.sum(1, 2); // 3

Instance methods

class Example { constructor() { this.sum = (a, b) => { console.log(a + b); } } }

Class Instantiation

new

Instantiation of a class must use the new keyword.

class Example {} let exam1 = Example(); // Class constructor Example cannot be invoked without 'new'

Instantiated object

Shared prototype object

class Example { constructor(a, b) { this.a = a; this.b = b; console.log('Example'); } sum() { return this.a + this.b; } } let exam1 = new Example(2, 1); let exam2 = new Example(3, 1); //__proto__ is deprecated and not recommended. // console.log(exam1.__proto__ == exam2.__proto__); console.log(Object.getPrototypeOf(exam1) === Object.getPrototypeOf(exam2));// true Object.getPrototypeOf(exam1).sub = function() { return this.a - this.b; } console.log(exam1.sub()); // 1 console.log(exam2.sub()); // 2

decorator

A decorator is a function used to modify the behavior of a class, taking effect at code compilation time.

Class Decorator

One parameter

The first parameter, target, points to the class itself.

function testable(target) { target.isTestable = true; } @testable class Example {} Example.isTestable; // true

Multiple parameters — nested implementation

function testable(isTestable) { return function(target) { target.isTestable=isTestable; } } @testable(true) class Example {} Example.isTestable; // true

Instance properties

The two examples above add static properties. To add instance properties, simply operate on the class's prototype.

Method Decorator

Three parameters: target (the class's prototype object), name (the modified property name), descriptor (the property's descriptor object).

class Example { @writable sum(a, b) { return a + b; } } function writable(target, name, descriptor) { descriptor.writable = false; return descriptor; //Must return }

Decorator execution order

Enters from outside in, executes from inside out.

class Example { @logMethod(1) @logMethod(2) sum(a, b){ return a + b; } } function logMethod(id) { console.log('evaluated logMethod'+id); return (target, name, desctiptor) => console.log('excuted logMethod '+id); } // evaluated logMethod 1 // evaluated logMethod 2 // excuted logMethod 2 // excuted logMethod 1

Encapsulation and Inheritance

getter / setter

Definition

class Example{ constructor(a, b) { this.a = a; //The set method is called upon instantiation this.b = b; } get a(){ console.log('getter'); return this.a; } set a(a){ console.log('setter'); this.a = a; //Self-recursive call } } let exam = new Example(1,2); //Continuously outputs setter, eventually causing RangeError class Example1{ constructor(a, b) { this.a = a; this.b = b; } get a(){ console.log('getter'); return this._a; } set a(a){ console.log('setter'); this._a = a; } } let exam1 = new Example1(1,2); //Only outputs setter, does not call getter method console.log(exam1._a); //1, can be accessed directly

getter cannot appear alone

class Example { constructor(a) { this.a = a; } get a() { return this.a; } } let exam = new Example(1); // Uncaught TypeError: Cannot set property // a of #<Example> which has only a getter

getter and setter must appear at the same level

class Father { constructor(){} get a() { return this._a; } } class Child extends Father { constructor(){ super(); } set a(a) { this._a = a; } } let test = new Child(); test.a = 2; console.log(test.a); // undefined class Father1 { constructor(){} //Or put both in the subclass get a() { return this._a; } set a(a) { this._a = a; } } class Child1 extends Father1 { constructor(){ super(); } } let test1 = new Child1(); test1.a = 2; console.log(test1.a); // 2

extends

Inheritance of classes is implemented through extends.

class Child extends Father { ... }

super

The subclass constructor method must contain super, and it must appear before this.

class Father { constructor() {} } class Child extends Father { constructor() {} // or // constructor(a) { // this.a = a; // super(); // } } let test = new Child(); // Uncaught ReferenceError: Must call super // constructor in derived class before accessing 'this' or returning // from derived constructor

Calling the parent class constructor can only appear in the subclass constructor.

class Father { test(){ return 0; } static test1(){ return 1; } } class Child extends Father { constructor(){ super(); } } class Child1 extends Father { test2() { super(); // Uncaught SyntaxError: 'super' keyword unexpected // here } }

Calling parent class methods: super, as an object, points to the parent class's prototype object in normal methods, and to the parent class in static methods.

class Child2 extends Father { constructor(){ super(); //Calling parent class normal methods console.log(super.test()); // 0 } static test3(){ //Calling parent class static methods return super.test1+2; } } Child2.test3(); // 3

Important Notes

Cannot inherit regular objects.

var Father = { // ... } class Child extends Father { // ... } // Uncaught TypeError: Class extends value #<Object> is not a constructor or null //Solution Object.setPrototypeOf(Child.prototype, Father);