Code reuse and its principles
代码复用, as the name suggests, is to reuse part or even all of the code that has been written to build a new program. When talking about code reuse, the first thing we can think of is继承性. The principle of code reuse is:
优先使用对象组合,而不是类继承In js, since there is no concept of class, the concept of instances is not very meaningful. Objects in js are simple key-value pairs that can be created and modified dynamically.
But in js , we can instantiate an object using constructors and new operators, which has syntax similarity to other programming languages that use classes.
For example:
var trigkit4 = new Person(); js seems to be a class when calling the constructor Person , but it is actually still a function, which gives us some development ideas and inheritance patterns that are assumed to be based on the class, which we can call "classical inheritance patterns".
The traditional inheritance model requires the class keyword. We assume that the above class inheritance model is现代继承模式, which is a model that does not need to be considered in a class way.
Classical inheritance mode
See the following two examples of the constructor Parent() and Child() :
<script type="text/javascript">function Parent(name){
this.name = name || 'Allen';
}
Parent.prototype.say = function(){
return this.name;
}
function Child(name){}
//Create an object with the Parent constructor and assign the object to the Child prototype to achieve inheritance
function inherit(C,P){
C.prototype = new P();//Prototype attribute should point to an object, not a function
}
//Calling the declared inherited function
inherit(Child, Parent);
</script>
When an object is created using the new Child() statement, it obtains its functionality from Parent() instance through the prototype, such as:
var kid = new Child();kid.say();//AllenPrototype chain
Let's discuss how prototype chains work in class inheritance mode. We think of objects as blocks somewhere in memory that contain data and references to other blocks. When an object is created using the new Parent() statement, a block like this on the left of the figure below will be created. This block saves name attribute. If you want to access say() method, we can access Parent.prototype __proto__ on the right by pointing to prototype attribute of the constructor Parent() .
So, what happens when creating a new object with var kid = new Child() ? As shown in the figure below:
The object created using new Child() statement is almost empty except for the implicit link __proto__ . In this case, __proto__ points to the object created using the new Parent() statement in the inherit() function
When executing kid.say() , since the block object in the lower left corner does not have say() method, it will query the middle block object through the prototype chain. However, the middle block object also does not have say() method, so it follows the prototype chain to query the rightmost block object, and the object happens to have say() method. Is it finished?
The execution is not finished here. this.name is referenced in say() method, which points to the object created by the constructor. Here, it points to the block new Child() . However, there is no name attribute in new Child() . For this reason, the intermediate block will be queryed, and the intermediate block happens to have name attribute. At this point, the query of the prototype chain has been completed.
For more detailed discussion, please check out my article: JavaScript Learning Notes (V) Detailed explanation of prototypes and prototype chains
Shared prototype
The rule of this pattern is that reusable members should be transferred to the prototype rather than placed in this. Therefore, for the purpose of inheritance, anything worth inheriting should be implemented in the prototype. Therefore, you can set the prototype of the child object and the prototype of the parent object to the same as the example below:
function inherit(C,P){C.prototype = P.prototype;
}
The child object and the parent object share the same prototype and can access say() method equally. However, the child object does not inherit name attribute
Prototype inheritance
Prototype inheritance is a "modern" classless inheritance model. See the following example:
<script type="text/javascript">//The object to be inherited
var parent = {
name: "Jack" //There is no semicolon here
};
//新对象var child = Object(parent);
alert(child.name);//Jack</script>
In prototype mode, it is not necessary to use object literals to create parent objects. As shown in the following code, you can use the constructor to create the parent object. In doing so, both its own properties and the properties of the constructor's prototype will be inherited.
<script type="text/javascript">// Parent constructor
function Person(){
this.name = "trigkit4";
}
//Add to prototype attribute
Person.prototype.getName = function(){
return this.name;
};
//Create a new Person class object
var obj = new Person();
//inherit
var kid = Object(obj);
alert(kid.getName());//trigkit4
</script>
In this mode, you can choose to inherit only the prototype object that exists in the existing constructor. Objects inherit from objects, regardless of how the parent object is created, as shown in the following example:
<script type="text/javascript">// Parent constructor
function Person(){
this.name = "trigkit4";
}
//Add to prototype attribute
Person.prototype.getName = function(){
return this.name;
};
//Create a new Person class object
var obj = new Person();
//inherit
var kid = Object(Person.prototype);
console.log(typeof kid.getName);//function, because it is in the prototype
console.log(typeof kid.name);//undefined, because only this prototype is inherited
</script>