Introduction
Four typesCodeThe reuse mode is the best practice and is recommended for programming.
Mode 1: Prototype inheritance
Prototype Inheritance refers to the prototype of parent objects as sub-objects to achieve the purpose of inheritance:
Function Object (o ){
Function F (){
}
F. Prototype = O;
Return New F ();
}
// Parent object to be inherited
VaR Parent = {
Name: "Papa"
};
// New Object
VaR Child = Object (parent );
// Test
Console. Log (child. Name ); // "Papa"
// Parent Constructor
Function Person (){
// An "own" Property
This . Name = "Adam ";
}
// Add new attributes to the prototype
Person. Prototype. getname = Function (){
Return This . Name;
};
// Create a new person
VaR Papa = New Person ();
// Inheritance
VaR KID = Object (PAPA );
Console. Log (kid. getname ()); // "Adam"
// Parent Constructor
Function Person (){
// An "own" Property
This . Name = "Adam ";
}
// Add new attributes to the prototype
Person. Prototype. getname = Function (){
Return This . Name;
};
// Inheritance
VaR KID = Object (person. Prototype );
Console. Log ( Typeof Kid. getname ); // "Function", because it is defined in the prototype
Console. Log ( Typeof Kid. Name ); // "Undefined", because only the prototype is inherited
At the same time, ecmascript5 provides a similar method called object. Create to inherit objects. The usage is as follows:
/*Use functions provided by ecmascript 5 in the new version*/
VaRChild = object. Create (parent );
VaRChild = object. Create (parent ,{
Age: {value: 2}//Ecma5 Descriptor
});
Console. Log (child. hasownproperty ("Age "));//True
In addition, attributes can be defined on the second parameter in a more fine-grained manner:
// First, define a new object man
VaR Man = object. Create ( Null );
// Next, create configuration settings that contain attributes.
// Set the attribute to writable, enumerable, and configurable.
VaR Config = {
Writable: True ,
Enumerable: True ,
Retriable: True
};
// Generally, object. defineproperty () is used to add new attributes (supported by ecmascript5)
// Now, for convenience, we can customize an encapsulation function.
VaR Defineprop = Function (OBJ, key, value ){
Config. value = value;
Object. defineproperty (OBJ, key, config );
}
Defineprop (man, 'car', 'delorean ');
Defineprop (man, 'dob', '123 ');
Defineprop (man, 'beard ', False );
Therefore, inheritance can be done as follows:
VaRDriver = object. Create (man );
Defineprop (driver, 'topspeed', '100mph ');
Driver. topspeed//100mph
However, you must note thatObject. Create (null)The prototype of the created object isUndefined, That is, noTostringAndValueofMethod, soAlert (man );ButAlert (man. Car );No problem.
Mode 2: Copy all attributes for inheritance
In this way, all attributes of the parent object are copied to the sub-object. Generally, the sub-object can use the data of the parent object.
Let's look at an example of a shallow copy:
/* Shortest copy */
Function Extend (parent, child ){
VaR I;
Child = Child | {};
For (I In Parent ){
If (Parent. hasownproperty (I )){
Child [I] = parent [I];
}
}
Return Child;
}
VaR Dad = {name: "Adam "};
VaR KID = extend (DAD );
Console. Log (kid. Name ); // "Adam"
VaR Dad = {
Counts: [1, 2, 3],
Reads: {paper: True }
};
VaR KID = extend (DAD );
Kid. counts. Push (4 );
Console. Log (DAD. counts. tostring ()); // "1, 2, 3, 4"
Console. Log (DAD. Reads === kid. Reads );// True
In the last line of the code, you can find that the reads of Dad and kid are the same, that is, they use the same reference, which is the problem caused by the shallow copy.
Let's take a look at the deep copy:
/* Deep copy */
Function Extenddeep (parent, child ){
VaR I,
Tostr = object. Prototype. tostring,
Astr = "[object array]";
Child = Child | {};
For (I In Parent ){
If (Parent. hasownproperty (I )){
If ( Typeof Parent [I] === 'object '){
Child [I] = (tostr. Call (parent [I]) === astr )? []: {};
Extenddeep (parent [I], child [I]);
} Else {
Child [I] = parent [I];
}
}
}
Return Child;
}
VaR Dad = {
Counts: [1, 2, 3],
Reads: {paper: True }
};
VaR KID = extenddeep (DAD );
Kid. counts. Push (4 );
Console. Log (kid. counts. tostring ()); // "1, 2, 3, 4"
Console. Log (DAD. counts. tostring ()); // "1, 2, 3"
Console. Log (DAD. Reads === kid. Reads ); // False
Kid. reads. Paper = False ;
After the deep copy, the two values are not equal, bingo!
Mode 3: Mix-in)
Mixing is to copy one or more (or all) attributes (or methods) of an object to another object. Let's take an example:
FunctionMix (){
VaRArg, prop, child = {};
For(ARG = 0; arg <arguments. length; Arg + = 1 ){
For(PropInArguments [Arg]) {
If(Arguments [Arg]. hasownproperty (PROP )){
Child [prop] = arguments [Arg] [prop];
}
}
}
ReturnChild;
}
VaRCake = mix (
{Eggs: 2, large:True},
{Butter: 1, salted:True},
{Flour: '3 cups '},
{Sugar: 'Sure! '}
);
Console. dir (cake );
The mix function copies the sub-attributes of all input parameters to the child object to generate a new object.
So how can we just mix some attributes? How to do this? In fact, we can use redundant parameters to define the attributes to be mixed in, such as mix (child, parent, Method1, method2) in this way, you can only mix Method1 and method2 in the parent into child. Code:
// Car
VaR Car = Function (Settings ){
This . Model = settings. model | 'no model provided ';
This . Color = settings. color | 'no color provided ';
};
// Mixin
VaR Mixin = Function (){};
Mixin. Prototype = {
Driveforward: Function (){
Console. Log ('Drive forward ');
},
Drivebackward: Function (){
Console. Log ('Drive backward ');
}
};
// The two parameters defined are the reciving object and the giving object)
Function Augment (receivingobj, givingobj ){
// If the specified method name is provided, three additional parameters are required.
If (Arguments [2]) {
For ( VaR I = 2, Len = arguments. length; I <Len; I ++ ){
Receivingobj. Prototype [arguments [I] = givingobj. Prototype [arguments [I];
}
}
// If you do not specify 3rd or more parameters, all the methods are mixed.
Else {
For ( VaR Methodname In Givingobj. Prototype ){
// Check whether the names to be included are not included in the processing object.
If (! Receivingobj. Prototype [methodname]) {
Receivingobj. Prototype [methodname] = givingobj. Prototype [methodname];
}
}
}
}
// Add attributes to the car, but the values are 'driveforward 'and 'drivebackward '*/
Augment (CAR, Mixin, 'driveforward ', 'drivebackward ');
// Create a new object car
VaR Vehicle = New Car ({model: 'Ford escort', color: 'blue '});
// Test whether the mixed-in method is obtained successfully
Vehicle. driveforward ();
Vehicle. drivebackward ();
This method is flexible to use.
Mode 4: Borrow Method
An object borrows one or two methods from another object, and there is no direct connection between the two objects. There is no need to explain more. Use the code to explain it directly:
VaR One = {
Name: 'object ',
Say: Function (GREET ){
Return Greet + ',' + This . Name;
}
};
// Test
Console. Log (one. Say ('Hi ')); // "Hi, object"
VaR Two = {
Name: 'Another Object'
};
Console. Log (one. Say. Apply (two, ['hello']); // "Hello, another object"
// Complex say to a variable. This points to the global variable.
VaR Say = one. Say;
Console. Log (say ('hoho ')); // "Hoho, undefined"
// Input a callback function callback
VaR Yetanother = {
Name: 'Et another object ',
Method: Function (Callback ){
Return Callback ('hola ');
}
};
Console. Log (yetanother. Method (one. Say ));// "Holla, undefined"
Function BIND (O, m ){
Return Function (){
Return M. Apply (O, []. Slice. Call (arguments ));
};
}
VaR Twosay = BIND (two, one. Say );
Console. Log (twosay ('yo ')); // "Yo, another object"
// Ecmascript 5 adds a BIND () method to function. prototype to make it easy to use apply () and call ().
If ( Typeof Function. Prototype. Bind === 'undefined '){
Function. Prototype. Bind = Function (Thisarg ){
VaR Fn = This ,
Slice = array. Prototype. Slice,
ARGs = slice. Call (arguments, 1 );
Return Function (){
Return FN. Apply (thisarg, argS. Concat (slice. Call (arguments )));
};
};
}
VaR Tw1_y2 = one. Say. BIND (two );
Console. Log (tw1_y2 ('bonjob ')); // "Bonjour, another object"
VaR Twpolicy3 = one. Say. BIND (two, 'enchant ');
Console. Log (twpolicy3 ());// "Enchanté, another object"
Transferred from: Uncle Tom