Home >Web Front-end >JS Tutorial >Alibaba technical articles share the implementation of Javascript inheritance mechanism_javascript skills
As a scripting language, Javascript was not designed with object-oriented features in mind. Even in this era of modern browsers and various Javascript frameworks/libraries mushrooming like mushrooms after a rain, there is not even a class keyword in Javascript. If you want to write a class, you have to use function. As for inheritance, overloading, etc., don't expect it.
But, how can we live without inheritance? Should we copy all the common logic to achieve the lowest level of code reuse?
The answer is of course - NO, so we have to implement inheritance ourselves!
Goal
The most critical goal is of course inheritance - the subclass automatically has all the public properties and methods of the parent class.
Support instanceof, for example, c is an instance of a subclass, and P is a parent class, c instanceof P should return true.
Secondly, you should be able to override (Override) the methods of the parent class, and in the methods of the subclass, you can easily call the method of the same name of the parent class.
As for overloading, it cannot be implemented due to the language characteristics of Javascript (methods cannot have the same name, even if their parameter lists are different).
Design and Implementation
Javascript objects have a very important attribute - __proto__, which is the prototype. A prototype is essentially an object, so it can also have its own prototype, thus forming a prototype chain. When you call a method of an object or read a property of the object, the Javascript executor does this:
1. First look for the corresponding method or attribute in the object. If it cannot be found,
2. Find the prototype of the object. If you still can’t find it,
3. Find
in the prototype’s prototype
4....
5. Until the prototype of Object is finally found, if not yet, return undefined
As shown below:
This feature of the prototype chain is very similar to inheritance, so naturally, we can use it to implement the inheritance mechanism. The prototype chain's support for instanceof makes it a good choice.
We define the extend function. This function accepts two parameters, the first is the parent class, and the second is the subclass, as shown below:
function extend(ParentClass, ChildClass) { ... return ChildClass; }
This function processes the subclass and returns the subclass. The processing logic is as follows:
Establish a prototype chain
By connecting the prototype chain of the subclass to the prototype chain of the parent class, the subclass can automatically have the methods and properties of the parent class:
var pp = ParentClass.prototype, cp = ChildClass.prototype; function T() {}; T.prototype = pp; ChildClass.prototype = new T();
In order to connect the prototype chain, you need to create an instance of the parent class and assign it to the prototype property of the child class. But we don't want to instantiate the parent class in the extend method, so we introduce an intermediate class T to solve this problem.
Implement rewriting
After the prototype chain is established, we also need to retain the methods and attributes on the original subclass prototype:
Method
If the parent class has a method with the same name, we use a closure to retain references to the parent class method and the child class method. Then, modify the reference to the method in the new prototype to point to a new function. In this function, we create a temporary attribute super, point it to the parent class method, and call the subclass method, so that in the subclass method, the parent class method can be called through this.super:
ChildClass.prototype[name] = (function(pm, cm) { return function() { var _super = this.super; this.super = pm; var result = cm.apply(this, arguments); this.super = _super; return result; }; })(pp[name], cp[name]);
Attributes
For attributes, there is no problem of overwriting, so just add the attributes in the original prototype of the subclass to the new prototype:
ChildClass.prototype[name] = cp[name];
Constructor
In order to allow the subclass to access the constructor of the parent class, we assign the parent class to the super attribute of the subclass:
ChildClass.super = ParentClass;
How to use
Suppose we want to design a management system that involves customers, workers, managers, etc. By abstracting the commonalities between customers and employees, we get People; then by abstracting the commonalities between workers and managers, we get Employee. In this way we get the three-level class structure:
The code to implement this design is as follows:
function People(firstname, lastname) { this.firstname = firstname; this.lastname = lastname; } function Employee(firstname, lastname, company) { Employee.super.apply(this, arguments); this.company = company; } function Manager(firstname, lastname, company, title) { Manager.super.apply(this, arguments); this.title = title; }
We want to have a description for each person. People is the name; employees include the company name after the name; and manager includes the position after the employee's description. The code is as follows:
People.prototype.summary = function() { return this.firstname + " " + this.lastname; }; Employee.prototype.summary = function() { return this.super.call(this) + ", " + this.company; }; Manager.prototype.summary = function() { return this.super.call(this) + ", " + this.title; };
After all member methods have been defined, declare the inheritance of the class (you must define the method first, and then declare the inheritance of the class, otherwise you cannot use this.super in the method to call the parent class method!):
extend(People, Employee); extend(Employee, Manager);
It is relatively simple to use these classes, just use new:
var people = new People("Alice", "Dickens"); var employee = new Employee("Bob", "Ray", "Alibaba"); var manager = new Manager("Calvin", "Klein", "Alibaba", "Senior Manager"); console.log( people.summary() ); //Alice Dickens console.log( employee.summary() ); //Bob Ray, Alibaba console.log( manager.summary() ); //Calvin Klein, Alibaba, Senior Manager
This article is good, so give it a like!