The original address: https://github.com/catchonme/blog/issues/3
We know that one of the biggest benefits of Class is the ability to implement inheritance, so that subclasses can reuse as much code as possible by inheriting from their parent Class.
So here’s the question
- How to implement subclasses to inherit the attributes and functions of their parent classes,
- When a subclass inherits from a parent class, why doesn’t the subclass’s function with the same name override the parent class’s function with the same name
We’ll look at prototype.js to see how ES5 implements Class
Prototype.js method for writing a Class
var Animal = Class.create({
initialize: function(name) {
this.name = name; }})var myAnimal = new Animal('jack');
console.log(myAnimal.name);// jack
var Cat = Class.create(Animal, {
initialize: function($super, name, age) {$super(name);
this.age = age; }})var myCat = new Cat('mia'.13);
console.log(myCat.name); // mia
console.log(myCat.age); / / 13
Copy the code
Create Class: Create a Class using class. create. The initialize function initializes the Class properties
Inheritance: Subclasses pass in the name of the parent Class as the first argument to class.create, and $super as the first argument to the function. Within the function, $super(args) is used to call the function of the same name
Then we look at the prototype.js internal implementation Class. Here’s the rough structure. The body is three functions, including an empty function
var Class = (function(){
var subclass() {}; / / empty function
function create() { // code... }
function addMethods() { // code... }
return {
create: create,
Methods: {
addMethods: addMethods
}
}
})();
Copy the code
So let’s break it down, what does the create function do?
function create(a) {
var parent = null, properties = [].slice.call(arguments);
// If the first argument passed is a function, it is the parent of the current class
if (isFunction(properties[0]))
parent = properties.shift();
// Create a klass function and execute initialize
function klass(a) {
this.initialize.apply(this, arguments);
}
// extend assigns class.methods attributes to klass
extend(klass, Class.Methods);
// Set the current class to parent
klass.superclass = parent;
klass.subclasses = [];
// If the current class has a parent class, we need to assign the attributes and functions of the parent class to the current class
if (parent) {
// The prototype of the parent class is assigned to the empty function subclass.prototype
subclass.prototype = parent.prototype;
// Assign klass.prototype by instantiating subclass so that klass can have the attributes and functions of its parent class
klass.prototype = new subclass;
parent.subclasses.push(klass)
}
// addMethods assigns all parameters passed to Klass's prototype, which will be explained later
for (var i=0, length=properties.length; i<length; i++) {
klass.addMethods(properties[i]);
}
if(! klass.prototype.initialize) { klass.prototype.initialize = emptyFunction } klass.prototype.constructor = klass;return klass
}
Copy the code
create
So what does the function do- new
klass
Function, executeinitialize
function - Determines if a parent class was passed in, and if so, assigns the attributes and functions of the parent class to the current class
- use
addMethods
Method to assign the user’s function toklass
的prototype
中
- new
If the prototype function of the parent class has the same name as the function of the subclass, then add the function of the parent class to the prototype. Why wouldn’t it be covered?
Let’s look at the addMethods function
function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype,
properties = Object.keys(source);
// Iterate over the passed functions, assigning each to the current prototype
for (var i=0, length=properties.length; i<length; i++) {
var property = properties[i], value = source[property];
// Check whether the first argument is $super
if (ancestor && isFunction(value)
&& value.argumentNames()[0] = ="$super") {
var method = value;
// This is the key to why subclasses can execute functions of the same name as their parent classes
value = (function (m) {
return function () {
The parent class executes the function of the same name once by passing the function name to the parent class, then
return ancestor[m].apply(this.arguments);
}
})(property).wrap(method); // wrap(method) executes the function of the same name of the current class again
// Override valueOf of the current function
value.valueOf = (function (method) {
return function () {
return method.valueOf.call(method);
}
})(method);
// Override toString for the current function
value.toString = (function (method) {
return function () {
return method.toString.call(method);
}
})(method);
}
// Assign the function to the prototype of the current class
this.prototype[property] = value; }}Copy the code
addMethods
What did you do?- Iterate over the function passed
- If the first argument to the function is
$super
Call the parent function with the same name once, and call the current class function with the same name once, so that can be implemented$super
The function of the parent class is called - If the function’s first argument is not
$super
, directly assigned to the current classprototype
中
- If the first argument to the function is
- Iterate over the function passed
The other utility functions used in the above functions, such as isFunction, extend, etc., are annotated in more detail by clicking here, since I have separated the prototype Class from js.
So let’s go back to the original question
- How do I inherit attributes and functions from a parent class?
- That instantiates the parent function through an intermediate variable and then assigns it to the child function
prototype
In this case, the function has the attributes and functions of the parent function
- That instantiates the parent function through an intermediate variable and then assigns it to the child function
- Why don’t subclasses overwrite functions of the same name as their parent class?
- Subfunctions set properties
superclass
Is the parent function assigned to the current class by all custom functions in the current classprototype
, will passsuperclass
Find the function with the same name of the parent class, so that when executing the function with the same name of the parent class, the function with the same name of the child class is executed once, and the function with the same name of the child class is executed once.
- Subfunctions set properties