Interface inheritance cannot be implemented in ECMAScript because the function is not signed. ECMAScript only supports inheritance, and its main way to realize inheritance depends on prototype chain.
Prototype chain inheritance
Relationship between constructor, prototype chain and instance: each constructor has a prototype object, each prototype object contains a pointer to the constructor, and each instance contains an internal pointer to the prototype object (_proto_).
All reference types inherit Object by default. This inheritance is also realized through the prototype chain.
Important: make the prototype of the child class equal to the instance of the parent class.
be careful:
- Subtypes sometimes need to override supertypes or add supertype methods. The code for adding methods to the prototype must be placed after replacing the prototype.
- When creating a subclass instance, you cannot pass parameters to the parent class.
- All new instances share the properties of the parent instance. (the properties on the prototype are shared. If one instance modifies the prototype properties, the prototype properties of another instance will also be modified!)
- The constructor of the prototype of the subclass will point to the constructor of the prototype (_proto_) of the new prototype of the subclass (instance of the parent class).
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // Subclass function Child() { this.name = 'kid' } Child.prototype = new Person(); // Prototype chain inheritance focus
Borrowing constructor inheritance
Important: call the parent constructor inside the subclass constructor, and use the call() and apply() methods to introduce the parent constructor into the subclass constructor.
advantage:
- It solves the shortcomings of prototype chain inheritance
- You can inherit multiple constructors (call / apply).
- You can pass parameters to the parent class.
Disadvantages:
- Only the properties of the parent class constructor can be inherited, and the properties of the parent class prototype are not inherited.
- Cannot implement reuse of constructors.
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // Subclass function Child() { Person.call(this, 'hhhqzh'); // Borrowing constructor inheritance focus this.name = 'kid'; }
Composite inheritance (pseudo classical inheritance; prototype chain + borrowing constructor) common
Combine the prototype chain foundation with borrowing constructor inheritance.
The prototype chain is used to inherit the prototype properties and methods of the parent class, and the constructor is used to inherit the instance properties. Guarantee not only realizes the reuse of functions by defining methods on the prototype, but also ensures that each instance has its own attributes.
Key point: combining advantages of the two inheritance modes, transfer participation and reuse.
advantage:
- You can inherit the properties and methods on the parent class prototype, and you can pass parameters and reuse the parent class constructor.
- The constructor properties introduced by each subclass instance are private and not shared like prototype chain inheritance.
Disadvantages:
- Call the parent constructor twice (memory consumption).
- The constructor of the prototype of the subclass will point to the constructor of the prototype (_proto_) of the new prototype of the subclass (instance of the parent class).
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // Subclass function Child(name) { Person.call(this, name); // Borrowing constructor inheritance focus } Child.prototype = new Person(); // Prototype chain inheritance focus let child = new Child('hhhqzh'); console.log(child.name); // hhhqzh inherits the properties of the parent constructor console.log(child.age); // 18 inherit the properties of the parent class prototype
Prototype inheritance
Prototypes allow you to create new objects based on existing objects without having to create custom types.
Important: you must have an object as the basis of another object, wrap an object with a function, and then return a new object.
Features: similar to copying an object, wrapped with functions. Object.create takes advantage of this principle.
Disadvantages:
- All instances inherit properties on the prototype.
- Reuse cannot be achieved. (the properties of the new instance are added after)
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // First encapsulate a function container, create a temporary constructor inside the function, then take the incoming object as the prototype of the constructor, and finally return an instance of the constructor. function object(obj) { function F(){}; F.prototype = obj; return new F(); } let person = new Person('hhhqzh'); let child = object(person); console.log(child.name); // hhhqzh inherits the properties of the parent function
Parasitic inheritance
Create a function that is only used to encapsulate the integration process, enhance the object within the function (any function that can return a new object, such as prototype inheritance), and finally return the object.
Disadvantages: no prototype is used and reuse cannot be realized.
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // First encapsulate a function container, create a temporary constructor inside the function, then take the incoming object as the prototype of the constructor, and finally return an instance of the constructor. function object(obj) { function F(); F.prototype = obj; return new F(); } // Create a function that encapsulates the inheritance process, which internally enhances the object in some way. function creeateAnother(original){ let clone = object(original); // Inheritance process clone.name = 'ppptyp'; clone.sayHi = function() { console.log("hi"); } return clone; } let person = new Person('hhhqzh'); let child = creeateAnother(person); child.sayHi(); // hi console.log(child.name); // ppptyp
Parasitic combinatorial inheritance (common)
That is, it inherits attributes by borrowing constructors, and inherits methods through the hybrid form of prototype chain. In essence, parasitic inheritance is used to inherit the prototype of the parent type (the prototype of the parent class is equal to an instance), and then assign this instance to the prototype of the child type.
Advantage: fixed the problem of composite inheritance (calling constructor twice)
// Parent class function Person(name) { this.name = name; this.sum = function() { console.log(this.name) } } Person.prototype.age = 18; // Subclass function Child(name) { Person.call(this, name); // Borrowing constructor inheritance } // Prototype inheritance function object(obj) { function F(); F.prototype = obj; return new F(); } // parasitic function creeateAnother(Child, Person){ let prototype = object(Person.prototype); // Inheritance process prototype.constructor = Child; Child.prototype = prototype; } // Child.prototype = new Person(); // Prototype chain inheritance creeateAnother(Child, Person); // Replace prototype chain inheritance let child = new Child('hhhqzh'); console.log(child.name); // hhhqzh inherits the properties of the parent constructor console.log(child.age); // 18 inherit the properties of the parent class prototype