1. Abstract Base Class
Sometimes it may be necessary to define a class that can be inherited by other classes but not instantiated itself. Although ECMAScript does not
There is a syntax that specifically supports this class, but it is also easy to implement through new.target. New.target saved with new keyword keys
Class or function used. Instantiation of abstract base classes can be prevented by detecting whether new.target is an abstract base class when instantiating:
Abstract Base Class
class Vehicle { constructor() { console.log(new.target); if (new.target === Vehicle) { throw new Error('Vehicle cannot be directly instantiated'); class Bus extends Vehicle {} new Bus(); // class Bus {} new Vehicle(); // class Vehicle {} // Error: Vehicle cannot be directly instantiated
In addition, by checking in the abstract base class constructor, you can require that a derived class must define a method. Because the prototype method is
Class constructors already exist before they are called, so the this keyword can be used to check the appropriate method:
Abstract Base Class
class Vehicle { constructor() { if (new.target === Vehicle) { throw new Error('Vehicle cannot be directly instantiated'); } if (!this.foo) { throw new Error('Inheriting class must define foo()'); } console.log('success!'); } }
Derived Class
class Bus extends Vehicle { foo() {} }
Derived Class
class Van extends Vehicle {} new Bus(); // success! new Van(); // Error: Inheriting class must define foo()
2. Inherit built-in types
The ES6 class provides a smooth mechanism for inheriting built-in reference types, which developers can easily extend:
shuffle algorithm class SuperArray extends Array { shuffle() { for (let i = this.length - 1; i > 0; i--) { const j = Math.floor(Math.random() * (i + 1)); [this[i], this[j]] = [this[j], this[i]]; } } } let a = new SuperArray(1, 2, 3, 4, 5); console.log(a instanceof Array); // true console.log(a instanceof SuperArray); // true 8.4 class 263 console.log(a); // [1, 2, 3, 4, 5] a.shuffle(); console.log(a); // [3, 1, 4, 5, 2]
Some methods of built-in types return new instances. By default, the type of returned instance is the same as that of the original instance:
class SuperArray extends Array {} let a1 = new SuperArray(1, 2, 3, 4, 5); let a2 = a1.filter(x => !!(x%2)) console.log(a1); // [1, 2, 3, 4, 5] console.log(a2); // [1, 3, 5] console.log(a1 instanceof SuperArray); // true console.log(a2 instanceof SuperArray); // true
If you want to override this default behavior, you can override the Symbol.species accessor, which decides to return the
Classes used in the instance:
class SuperArray extends Array { **static get [Symbol.species]() {** **return Array;** **}** } let a1 = new SuperArray(1, 2, 3, 4, 5); let a2 = a1.filter(x => !!(x%2)) console.log(a1); // [1, 2, 3, 4, 5] console.log(a2); // [1, 3, 5] console.log(a1 instanceof SuperArray); // true **console.log(a2 instanceof SuperArray); // false**
3. Class Mixing
Aggregating the behavior of different classes into one class is a common JavaScript pattern. Although ES6 does not explicitly support multiple inheritance, it does
This behavior can be easily simulated with existing features.
Note that the Object.assign() method is designed to blend in object behavior. Only behavior that requires mixing classes
Then it is necessary to implement the mixed expression yourself. If you just need to mix attributes of multiple objects, use
Object.assign() is OK.
In the code snippet below, the extends keyword is followed by a JavaScript expression. Any that can be parsed into a class or
The expressions for each constructor are valid. This expression is evaluated when evaluating the class definition:
class Vehicle {} function getParentClass() { console.log('evaluated expression'); return Vehicle; class Bus extends **getParentClass()** {} }
Evaluable expression
Mixing patterns can be achieved by concatenating multiple mixed elements in an expression that eventually resolves to an expression that can be
Inherited class. If the Person class needs to combine A, B, C, then it needs some mechanism to implement B inherit A, C inherit B, and
Then inherit C to combine A, B, and C into this superclass. There are different strategies for implementing this pattern.
A strategy is to define a set of "nestable" functions, each receiving a superclass as a parameter, and a mixed class as
Subclass of this parameter and returns this class. These combinatorial functions can be called concatenatively and ultimately combined into superclass expressions:
class Vehicle {} let FooMixin = (Superclass) => class extends Superclass { foo() { console.log('foo'); } }; let BarMixin = (Superclass) => class extends Superclass { bar() { console.log('bar'); } }; let BazMixin = (Superclass) => class extends Superclass { baz() { console.log('baz'); } }; class Bus extends FooMixin(BarMixin(BazMixin(Vehicle))) {} let b = new Bus(); b.foo(); // foo b.bar(); // bar b.baz(); // baz
Nested calls can be expanded by writing an auxiliary function:
class Vehicle {} let FooMixin = (Superclass) => class extends Superclass { foo() { console.log('foo'); } }; let BarMixin = (Superclass) => class extends Superclass { bar() { console.log('bar'); } }; let BazMixin = (Superclass) => class extends Superclass { baz() { console.log('baz'); } }; **function mix(BaseClass, ...Mixins) {** **return Mixins.reduce((accumulator, current) => current(accumulator), BaseClass);** **}** **class Bus extends mix(Vehicle, FooMixin, BarMixin, BazMixin) {}** let b = new Bus(); b.foo(); // foo b.bar(); // bar b.baz(); // baz
Note that many JavaScript frameworks, especially React, have abandoned the mixed mode and moved to the combined mode (putting methods in place)
Extract into separate classes and auxiliary objects and combine them without inheritance). This reflects the crowd
Well-known software design principle: "composition over inheritance". This design principle is
Many people follow and offer great flexibility in code design
summary
That's what it is today JavaScript Advanced Programming (2) Inheritance Will keep updating... Originality is not easy. We look forward to your comments and comments😜😜