1, using the new keyword to generate an example
Working with form validation this simple scripting language obviously does not require an "inheritance" mechanism, but if JavaScript is an object, there is a way to connect all objects. Finally, Brendan Eich still designed "inheritance." It's just that he didn't introduce the concept of class, because JavaScript is a complete object-oriented programming language once you have a "class".
This seems a bit too formal, and the design of the original intention is also far, while increasing the beginner's difficulty in getting started.
References to C + + and the Java language Use the new command to generate an instance:
C + + writes this:
The code is as follows |
Copy Code |
ClassName *object = new ClassName (param); Java writes this: Foo foo = new Foo ();
|
You can also introduce the new command into JavaScript, which is used to generate an instance object from a prototype object. However, there is no "class" in JavaScript, how to represent the prototype object?
The constructor function (constructor) of the class is invoked when the new command is still referenced in C + + and Java. Brendan Eich simplifies design, in JavaScript language, the new command is followed by a constructor, no longer a class.
For example, there is now a prototype called a WD constructor that represents a front-end development (Web-developper) object.
The code is as follows |
Copy Code |
function WD (skill) { This.skill = skill; }
|
With the new keyword for this constructor, an instance of the front-end development object is generated.
The code is as follows |
Copy Code |
var WD1 = new WD (' HTML '); Console.log (Wd1.skill); Html
|
The This keyword in the constructor, which actually represents the newly created instance object.
2, new out of the object of the defect
Using the new keyword, generating instance objects with constructors cannot share properties and methods.
For example, in a WD object's constructor, set a common property skill for an instance object.
The code is as follows |
Copy Code |
function WD (skill) { This.skill = skill; This.sex = ' Male '; }
|
Then, two instance objects are generated:
The code is as follows |
Copy Code |
var WD1 = new WD (' HTML '); var WD2 = new WD (' CSS ');
|
The skill property of the two objects is independent, and modifying one does not affect the other.
The code is as follows |
Copy Code |
Wd1.skill= ' Javascript '; Console.log (Wd2.skill);//"CSS", unaffected by WD1
|
Each instance object has its own copy of the properties and methods. This not only can not do data sharing, but also a huge waste of resources.
3, the introduction of prototype properties
To implement the sharing of properties and methods, Brendan Eich decides to set a prototype property for the constructor.
This property contains an object (hereinafter referred to as "prototype object") in which all instance objects need to be shared properties and methods, all of which are placed inside the object, and those that do not need to be shared are placed inside the constructor.
Once the instance object is created, the properties and methods of the prototype object are automatically referenced. That is, the properties and methods of an instance object are divided into two types, one local and the other referenced.
Or as an example of a WD constructor, now overwrite with the prototype property:
The code is as follows |
Copy Code |
function WD (skill) { This.skill = skill; } Wd.prototype = {sex: ' Male '}; var WD1 = new WD (' HTML '); var WD2 = new WD (' CSS '); Console.log (Wd1.sex); Man Console.log (Wd2.sex); Man |
Now, the sex attribute is placed in the prototype object and is shared by two instance objects. As long as the prototype object is modified, it affects two instance objects at the same time.
The code is as follows |
Copy Code |
WD.prototype.sex = ' female '; Console.log (Wd1.sex); Woman Console.log (Wd2.sex); Woman
|
Since all instance objects share the same prototype object, the prototype object looks like the prototype of the instance object from the outside, and the instance object seems to "inherit" the prototype object. This is the design idea of the JavaScript inheritance mechanism.
Iii. How constructors Implement inheritance
There is now a constructor for an "MED" Object (med:marketing experience design, marketing experience)
The code is as follows |
Copy Code |
function MED () { This.aim = "Marketing experience Design"; } is still the constructor of the "WD" object, function WD (skill,sex) { This.skill = skill; This.sex = sex; }
|
How can we make "WD" Inherit "MED"?
1. Apply binding constructor implementation
The simplest method, presumably, is to use the call or Apply method to bind the parent object's constructor to a child object, which is to add a row to the child object constructor:
The code is as follows |
Copy Code |
function WD (skill,sex) { Med.apply (this, arguments); This.skill = skill; This.sex = sex; } var WD1 = new WD ("Html", "male"); Console.log (Wd1.aim); "Marketing Experience Design" |
2. Prototype Mode implementation
Our usual practice is to use the prototype property. If the prototype object of "WD" points to an instance of Med, then all instances of "WD" can inherit Med.
The code is as follows |
Copy Code |
Wd.prototype = new Med ()//We point the prototype object of WD to an instance of Med. WD.prototype.constructor = WD; var WD1 = new WD ("Html", "male"); Console.log (Wd1.aim); Marketing Experience Design
|
This sentence
The code is as follows |
Copy Code |
Wd.prototype = new MED ();
|
This is equivalent to completely removing the original value of the prototype object and then assigning a new value. So what does the second line mean?
The code is as follows |
Copy Code |
WD.prototype.constructor = WD;
|
It turns out that any prototype object has a constructor property that points to its constructor. That is to say, Wd.prototype the object's constructor attribute, pointing to WD.
We have deleted the original value of this prototype object in the previous step, so the new prototype object has no constructor attribute, we need to add it manually, otherwise the "inheritance chain" will go wrong. That's what the second line means.
Note that this is a very important point to be sure to follow in programming, as follows, that is, if you replace the prototype object,
The code is as follows |
Copy Code |
O.prototype = {};
|
The next step, then, is necessarily to add the constructor attribute to the new prototype object and refer back to the original constructor.
The code is as follows |
Copy Code |
O.prototype.constructor = O;
|
3. Direct inheritance from prototype implementation
Because of the Med object, the invariant properties can be written directly to the Med.prototype. So, we can also let WD () skip MED () and inherit Med.prototype directly.
Now, let's rewrite the Med object:
The code is as follows |
Copy Code |
function MED () {} MED.prototype.skill = "MED"; |
Then, the prototype object of WD points to the Med prototype object, which completes the inheritance.
The code is as follows |
Copy Code |
Wd.prototype = Med.prototype; WD.prototype.constructor = WD; var WD1 = new WD ("Html", "male"); Console.log (Wd1.skill); MED |
Compared to the previous method, the advantage of this is that it is more efficient (do not need to execute and establish an instance of the Med), compared to save memory. The disadvantage is that Wd.prototype and Med.prototype now point to the same object, and any changes to Wd.prototype will be reflected in Med.prototype.
So, the above section of code is actually problematic. Please look at the second line
The code is as follows |
Copy Code |
WD.prototype.constructor = WD; This sentence actually put the Med.prototype object's constructor attribute also to get rid of! Console.log (MED.prototype.constructor); Wd
|
4. Use an empty object as an intermediary to implement
Because of the above disadvantages of "direct inheritance prototype", an empty object can be used as an intermediary.
The code is as follows |
Copy Code |
var F = function () {}; F.prototype = Med.prototype; Wd.prototype = new F (); WD.prototype.constructor = WD; F is an empty object, so it hardly takes up memory. At this point, modify the WD prototype object, will not affect the prototype object of the Med. Console.log (MED.prototype.constructor); MED |
5. The encapsulation function using prototype mode
We encapsulate the above method into a function that is easy to use.
The code is as follows |
Copy Code |
function extend (child, Parent) { var F = function () {}; F.prototype = Parent.prototype; Child.prototype = new F (); Child.prototype.constructor = child; } |
When used, the method is as follows
The code is as follows |
Copy Code |
Extend (wd,med); var WD1 = new WD ("Html", "male"); Console.log (Wd1.aim); Marketing Experience Design
|
This extend function is the Yui library how to implement the method of inheritance.
6. Copy Inheritance Implementation
The above is a prototype way to implement inheritance. In fact, since the child object will have the parent object's properties and methods, we directly use the "copy" method can also achieve the effect. Simply put, if you copy all the properties and methods of a parent object into a child object, can you not inherit it?
First, all the invariant properties of Med are placed on its prototype object.
The code is as follows |
Copy Code |
function MED () {} MED.prototype.aim = "Marketing experience Design"; |
Then, write a function that implements the purpose of the property copy.
The code is as follows |
Copy Code |
function extendcopy (Child, Parent) { var p = parent.prototype; var c = Child.prototype; for (var i in P) { C[i] = P[i]; } }
|
The function is to copy the properties of the parent object's prototype object, one by one to the prototype object of the child object.
When used, write like this:
The code is as follows |
Copy Code |
Extendcopy (WD, MED); var WD1 = new WD ("Html", "male"); Console.log (Wd1.aim); Marketing Experience Design
|
How to implement the inheritance of "non-constructor"
For example, now there is an object called "MED" – The marketing experience design.
The code is as follows |
Copy Code |
var MED = { Aim: ' Marketing experience design ' }
|
There is also an object called "Front-End development."
The code is as follows |
Copy Code |
var WD ={ Skill: ' HTML ' }
|
How can I let "front-end development" to inherit "marketing experience design", that is, how can I generate a "marketing experience design Front-End development" object?
Notice here that both objects are normal objects, not constructors, and cannot be implemented with the constructor method.
1. Object () method
The JSON-formatted inventor Douglas Crockford, presents an object () function that can do this.
The code is as follows |
Copy Code |
function Object (o) { function F () {} F.prototype = O; return new F (); } |
This object () function, in fact, only do one thing, that is, the object of the prototype attribute, point to the parent object, so that child objects and the parent object together.
When used, the first step is to generate child objects on the basis of the parent object:
The code is as follows |
Copy Code |
var WD = object (MED);
|
Then, plus the properties of the child object itself:
The code is as follows |
Copy Code |
Wd.skill = ' html ';
|
At this point, the child object has inherited the properties of the parent object.
The code is as follows |
Copy Code |
Console.log (Wd.aim); Marketing Experience Design
|
2, Shallow copy
In addition to using the "prototype chain", there is another idea: the parent object's attributes, all copied to the child object, can also implement inheritance.
The following function is making a copy:
The code is as follows |
Copy Code |
function Lightcopy (p) { var c = {}; for (var i in P) { C[i] = P[i]; } C.uber = p; return C; } |
When used, write like this:
The code is as follows |
Copy Code |
var WD = lightcopy (MED); Wd.aim = ' Front-End development ';
|
However, there is a problem with such a copy. That is, if the parent object's properties are equal to an array or another object, the child object actually gets only a memory address, not a real copy, so there is a possibility that the parent object has been tampered with.
See, now add a "skill" attribute to Med, whose value is an array.
The code is as follows |
Copy Code |
Med.skills = [' html ', ' CSS ', ' Javascript '];
|
Through the Lightcopy () function, WD inherits the Med.
The code is as follows |
Copy Code |
var WD = lightcopy (MED);
|
Then, we add a property for WD's "skills":
The code is as follows |
Copy Code |
WD.skills.push (' teamwork ');
|
What happened? Med's "skills" have also been tampered with!
The code is as follows |
Copy Code |
Console.log (Wd.skills); ' HTML ', ' Javascript ', ' css ', ' teamwork ' Console.log (Med.skills); ' HTML ', ' Javascript ', ' css ', ' teamwork '
|
So, lightcopy () just copies the basic type of data, and we call this copy "shallow copy." This is how early jquery implements inheritance.
3, deep copy
The so-called "deep copy" is the ability to achieve the true meaning of the array and the copy of the object. Its implementation is not difficult, as long as the recursive call "shallow copy" on the line.
The code is as follows |
Copy Code |
function Deepcopy (p, c) { var c = C | | {}; for (var i in P) { if (typeof p[i] = = = ' object ') { C[i] = (P[i].constructor = = Array)? [] : {}; Deepcopy (P[i], c[i]); } else { C[i] = P[i]; } } return C; } |
When used, write this:
The code is as follows |
Copy Code |
var WD = deepcopy (MED);
|
Now, add a property to the parent object, and the value is an array. Then, modify the property on the child object:
The code is as follows |
Copy Code |
Med.skills = [' html ', ' CSS ', ' Javascript ']; WD.skills.push (' teamwork ');
|
At this point, the parent object will not be affected.
The code is as follows |
Copy Code |
Console.log (Wd.skills); ' HTML ', ' CSS ', ' Javascript ', ' teamwork ' Console.log (Med.skills); ' HTML ', ' CSS ', ' Javascript '
|