Deep understanding of JavaScript Series (46): Code reuse Mode (recommended) detailed _javascript tips

Source: Internet
Author: User
Tags configuration settings extend mixed shallow copy hasownproperty

Introduced

The four code reuse patterns described in this article are best practices and are recommended for use in the programming process.

Mode 1: Prototype inheritance

Prototype inheritance is the prototype of having the parent object as a child object to achieve the purpose of inheritance:

Copy Code code as follows:

function Object (o) {
function F () {
}

F.prototype = O;
return new F ();
}

The parent object to inherit
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";
}
To add a new attribute to a stereotype
Person.prototype.getName = function () {
return this.name;
};
Create a new person
var papa = new Person ();
Inherited
var Kid = object (papa);
Console.log (Kid.getname ()); "Adam"


Parent constructor
function person () {
An ' own ' property
THIS.name = "Adam";
}
To add a new attribute to a stereotype
Person.prototype.getName = function () {
return this.name;
};
Inherited
var Kid = object (Person.prototype);
Console.log (typeof Kid.getname); "Function", because it's defined in the prototype.
Console.log (typeof Kid.name); "Undefined" because it inherits only the prototype


At the same time, ECMASCRIPT5 also provides a similar method called Object.create for inheriting objects, as follows:

Copy Code code as follows:

* * Use the new version of ECMAScript 5 features provided.
var child = object.create (parent);

var child = Object.create (parent, {
Age: {Value:2}//ECMA5 descriptor
});
Console.log (Child.hasownproperty ("Age")); True

Also, you can define attributes more fine-grained on the second parameter:

Copy Code code as follows:

First, define a new object man
var man = object.create (null);

Next, create the configuration settings that contain the properties
property is set to writable, enumerable, configurable
var config = {
Writable:true,
Enumerable:true,
Configurable:true
};

You typically use Object.defineproperty () to add new attributes (ECMAScript5 support)
Now, for convenience, we customize a wrapper function
var defineprop = function (obj, key, value) {
Config.value = value;
Object.defineproperty (obj, key, config);
}

Defineprop (Mans, ' car ', ' DeLorean ');
Defineprop (man, ' dob ', ' 1981 ');
Defineprop (Mans, ' beard ', false);

So the inheritance can be done:

Copy Code code as follows:

var driver = Object.create (mans);
Defineprop (Driver, ' topspeed ', ' 100mph ');
Driver.topspeed//100mph

One place to note, however, is that the object.create (NULL) created object has a prototype of undefined, that is, no ToString and valueof methods, so alert (man) is wrong, but alert (Man.car) ; it's no problem.

Mode 2: Copy all attributes for inheritance

The inheritance of this method is to copy all the attributes from the parent object to the child object, and the normal child object can use the parent object's data.

Let's take a look at an example of a shallow copy:

Copy Code code as follows:

/* Shallow Copy * *
function extend (parent, child) {
var i;
Child = Child | | {};
For (i in parent) {
if (Parent.hasownproperty (i)) {
Child[i] = Parent[i];
}
}
return to 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

The last line of code, you can see that Dad and kid reads are the same, they are using the same reference, which is the problem with the shallow copy.

Let's take another look at the deep copy:

Copy Code code as follows:

/* 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 a deep copy, two values are not equal, bingo!

Mode 3: Blending (mix-in)

Mixing is copying one or more (or all) attributes (or methods) of an object to another object, and we give an example:

Copy Code code as follows:

function Mix () {
var arg, prop, child = {};
for (arg = 0; arg < arguments.length; arg + 1) {
For (prop in Arguments[arg]) {
if (Arguments[arg].hasownproperty (prop)) {
Child[prop] = Arguments[arg][prop];
}
}
}
return to child;
}

var cake = Mix (
{eggs:2, large:true},
{butter:1, salted:true},
{flour: ' 3 cups '},
{sugar: ' sure! '}
);

Console.dir (cake);


The mix function copies the child properties of all the parameters passed in to the Children object in order to produce a new object.

So how about we just want to mix some of the attributes? How does it work? In fact, we can use the extra parameters to define the attributes that need to be mixed in, such as Mix (CHILD,PARENT,METHOD1,METHOD2) so that the method1 and METHOD2 in the parent can be mixed into the child. Code on:

Copy Code code as follows:

Car
var car = function (settings) {
This.model = Settings.model | | ' No model provided ';
This.colour = Settings.colour | | ' No colour provided ';
};

Mixin
var mixin = function () {};
Mixin.prototype = {
Driveforward:function () {
Console.log (' drive forward ');
},
Drivebackward:function () {
Console.log (' drive backward ');
}
};


The 2 parameters defined are the mixed objects (reciving) and where they are mixed (giving)
function augment (Receivingobj, givingobj) {
If the specified method name is provided, the parameter is 3 extra
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 a 3rd argument, or more arguments, you can mix all the methods
else {
For (Var methodname in Givingobj.prototype) {
Check that the receiving object does not contain the name to be mixed in, how to include it and not mix it
if (!receivingobj.prototype[methodname]) {
Receivingobj.prototype[methodname] = Givingobj.prototype[methodname];
}
}
}
}

Mix the properties with the car, but the value is mixed with ' driveforward ' and ' Drivebackward '.
Augment (car, mixin, ' Driveforward ', ' Drivebackward ');

Create new Object car
var vehicle = new Car ({model: ' Ford Escort ', Colour: ' Blue '});

Test whether successful get mixed method
Vehicle.driveforward ();
Vehicle.drivebackward ();

This method is more flexible to use.

Mode 4: Borrowing methods

One object borrows one or two methods of another object, and there is no direct connection between the two objects. No more explanations, just explain it in code:

Copy Code code as follows:

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"

Assign say to a variable, this will point to the global variable
var say = One.say;
Console.log (Say (' HoHo ')); "HoHo, undefined."

Pass in a callback function callback
var yetanother = {
Name: ' Yet 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 twosay2 = One.say.bind (two);
Console.log (Twosay2 (' Bonjour ')); "Bonjour, another object"

var twosay3 = One.say.bind (two, ' enchanté ');
Console.log (Twosay3 ()); "Enchanté, another object"

Summarize

You don't have to sum it up.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.