Summary of javascript inheritance and javascript learning experience

Source: Internet
Author: User
Tags hasownproperty

Summary of javascript inheritance and javascript learning experience

I have read a lot of js inheritance things and should summarize them.
Let's start with a rough understanding. If something is wrong, let's still look at it and correct the three views. In addition, the following example does not mean that the original variable name is basically changed, and some may even be used directly.

Js inheritance is used for the following purposes:

First, JavaScript does not really inherit the same concept as other object-oriented languages. The Inheritance mentioned in js refers to simulated inheritance.
What is the specific js inheritance? I used it for interviews when I first started working on the front-end. (I didn't use it when I first wrote some small results. Why, because the interviewer is very fond of asking this question), let's look at it. During the interview, let's say a rough picture. This is an interview party. In fact, although the concept is not very clear, it will also be used later.
What is actually used for? It is mainly used to reuse the code we have previously written. For example, if we have written a function, an object, or something written by someone else, we have to add something for ourselves. We can't change people's things, just inherit it and use it, this is the true purpose of inheritance.

How to Implement js inheritance:
Don't go to the code first. Let's talk about the idea first. In fact, inheritance is to find a way to get the attributes or methods of other objects (everything in js is an object) to our own objects so that our own objects can be used. This achieves the purpose of reuse.
The following is the implementation method.
Based on the characteristics of js, the implementation is nothing more than one or both of the following methods.

1. constructor. js does not seem to have a strict definition of constructor, but you can use new to create new objects. Constructor is also said to be a strict method for implementing the inheritance of object-oriented language, so javascript can simulate it, so people who have learned oop will first think of it.

2. Use the function prototype and prototype chain to link two objects. It is easy to think of this because the js prototype chain is unique.
There are also several prototype types: What is used as the prototype of the inherited object, the prototype of the inherited object, the instance of the inherited object, or the successor directly. The inheritance effects of the prototype of the inherited objects are different.

3. Copy attributes and methods, and copy and clone all the attributes or methods of the inherited object into the attributes and methods of our own object. Then we can use them smoothly. Of course, this is also divided into two scenarios: shallow replication and deep replication.

4. Using the call and apply methods, these two methods are amazing and can change the context (this) of function execution ), therefore, these two methods can be used to inherit and reuse methods of inherited objects.
 
In general, this is probably the way js implements inheritance. The ever-changing implementation methods are combined and upgraded based on these methods, and most of them need to be used in combination, of course, it is because the effect of using a single method is not ideal. Of course, you can choose which method to use based on the actual needs of your project, as long as you meet your needs, it does not mean which method must be used for implementation. It is like saying that the fastest flight from Beijing to Shijiazhuang is of course a plane. However, if you are far away from the airport, go to the airport, and go to the city from the airport, the overall calculation is not as fast as high-speed trains, then you can do high-speed trains. For example, if you have a car to drive, you can ride a bicycle if you want to challenge it. You can choose one based on your actual situation.


Code implementation: Let's talk about the above several implementation methods in combination with the Code, some of which are extracted from other places, and add some comments.
 

I have read a lot of js inheritance things and should summarize them.
Let's start with a rough understanding. If something is wrong, let's still look at it and correct the three views. In addition, the following example does not mean that the original variable name is basically changed, and some may even be used directly.

Js inheritance is used for the following purposes:

First, JavaScript does not really inherit the same concept as other object-oriented languages. The Inheritance mentioned in js refers to simulated inheritance.
What is the specific js inheritance? I used it for interviews when I first started working on the front-end. (I didn't use it when I first wrote some small results. Why, because the interviewer is very fond of asking this question), let's look at it. During the interview, let's say a rough picture. This is an interview party. In fact, although the concept is not very clear, it will also be used later.
What is actually used for? It is mainly used to reuse the code we have previously written. For example, if we have written a function, an object, or something written by someone else, we have to add something for ourselves. We can't change people's things, just inherit it and use it, this is the true purpose of inheritance.

How to Implement js inheritance:
Don't go to the code first. Let's talk about the idea first. In fact, inheritance is to find a way to get the attributes or methods of other objects (everything in js is an object) to our own objects so that our own objects can be used. This achieves the purpose of reuse.
The following is the implementation method.
Based on the characteristics of js, the implementation is nothing more than one or both of the following methods.

1. constructor. js does not seem to have a strict definition of constructor, but you can use new to create new objects. Constructor is also said to be a strict method for implementing the inheritance of object-oriented language, so javascript can simulate it, so people who have learned oop will first think of it.

2. Use the function prototype and prototype chain to link two objects. It is easy to think of this because the js prototype chain is unique.
There are also several prototype types: What is used as the prototype of the inherited object, the prototype of the inherited object, the instance of the inherited object, or the successor directly. The inheritance effects of the prototype of the inherited objects are different.

3. Copy attributes and methods, and copy and clone all the attributes or methods of the inherited object into the attributes and methods of our own object. Then we can use them smoothly. Of course, this is also divided into two scenarios: shallow replication and deep replication.

4. Using the call and apply methods, these two methods are amazing and can change the context (this) of function execution ), therefore, these two methods can be used to inherit and reuse methods of inherited objects.
 
In general, this is probably the way js implements inheritance. The ever-changing implementation methods are combined and upgraded based on these methods, and most of them need to be used in combination, of course, it is because the effect of using a single method is not ideal. Of course, you can choose which method to use based on the actual needs of your project, as long as you meet your needs, it does not mean which method must be used for implementation. It is like saying that the fastest flight from Beijing to Shijiazhuang is of course a plane. However, if you are far away from the airport, go to the airport, and go to the city from the airport, the overall calculation is not as fast as high-speed trains, then you can do high-speed trains. For example, if you have a car to drive, you can ride a bicycle if you want to challenge it. You can choose one based on your actual situation.


Code implementation: Let's talk about the above several implementation methods in combination with the Code, some of which are extracted from other places, and add some comments.
 

1. constructor implementation (borrow constructor ):

Function Super (arg) {this. arr1 = "I'm super" + arg; this. show = function () {alert (this. arr1) ;}} Super. prototype. say = function () {alert (this. arr1);} function suber (arg) {Super. apply (this, arguments); // In the context of suber, run super} var sub = new suber ("suber"); var sub2 = new suber ("suber1 "); console. log (sub. arr1); // I'm super suber console. log (sub. show); // function () {alert (this. arr1);} console. log (sub. say); // undefined console. log (sub. show === sub2.show); // false

Oh, I found sub. say is undefined, which means it has not been inherited. The show of the two sub and sub2 objects below is not equal. It means that the two functions point to two different objects, that is to say, two copies are copied.

Therefore, if this method is inherited, the attributes and methods on the prototype object are not inherited. The attributes and methods on Super are copied for each new object.
So it is not appropriate to use this method to implement inheritance, because the methods on the prototype are not inherited. So the great gods thought of prototype inheritance.

Ii. Prototype inheritance:

function Super(arg){      this.arr1 = "I'm super "+arg;      this.show = function(){        alert(this.arr1);      }    }    Super.prototype.say = function(){      alert(this.arr1);    }    function suber(arg){}    suber.prototype = new Super();    var sub = new suber("suber1");    var sub2 = new suber("suber2");    console.log(sub.arr1); //I'm super undefined    console.log(sub.show); //function (){ alert(this.arr1);}    console.log(sub.say); //function (){ alert(this.arr1);}    console.log(sub.show === sub2.show);  //true;    console.log(sub.say === sub2.say);  //true;


This is inherited by arr1, but the parameter is not added, it is undefined, so this parameter is passed in when the method subclass declaration is passed in and the property inherited by the class cannot be received. Other operations are normal. Both show and say are inherited. However, you must note that say is inherited from the super prototype object, while show is the attribute of the instance when the super object instance is created.

So how can we implement parameter transmission and inherit the stuff in the prototype? Of course, just combine the two methods above, so the predecessors invented the following method:


Iii. Combination inheritance (borrow constructor and set prototype ):

function Super(arg){      this.arr1 = "I'm super "+arg;      this.show = function(){        alert(this.arr1);      }    }    Super.prototype.say = function(){      alert(this.arr1);    }    function suber(arg){      Super.apply(this, arguments);    }    suber.prototype = new Super();    var sub = new suber("suber1");    var sub2 = new suber("suber2");    console.log(sub.arr1); //I'm super suber1    console.log(sub.show); //function (){ alert(this.arr1);}    console.log(sub.say); //function (){ alert(this.arr1);}    console.log(sub.show === sub2.show);  //false;    console.log(sub.say === sub2.say);  //true;

This is almost perfect, but we can find sub. show and sub2.show are not the same. Why? Because applying makes show a property of suber, in the suber prototype, the show (show of Super as the Instance Object of suber prototype object) is overwritten, so it becomes a copy every time. Of course, there is no way to avoid this. In order not to generate such redundant functions that can be shared, they can be placed in the prototype object.
Because of the calls in the suber construction and the calls made when the suber prototype object is assigned a value, Super is called twice, so the Super is called twice each time when the new suber object is created, two calls will generate two instance objects and consume extra resources.

So the predecessors opened a brain hole to solve this problem and developed the following method.
 

Iv. Parasitic combination inheritance:
The main difference between this method and method 3 is that the parent class prototype is assigned to the subclass prototype instead of the parent class. Let's look at the example.

 

Function Super (arg) {this. arr1 = "I'm super" + arg;} Super. prototype. show = function () {// this method is stored on the prototype object. Alert (this. arr1);} Super. prototype. say = function () {alert (this. arr1);} function suber (arg) {Super. apply (this, arguments);}/* The Role Of The inherit function, using a new empty function to cut off the direct connection between the prototype object of the parent class object and the subclass prototype object, instead, the instance object is inherited through the null structure, which can avoid modifying the attributes or methods of the subclass prototype and affecting the attributes or methods of the parent class prototype object. */Function inherit (obj) {function F () {} F. prototype = obj; return new F ();} suber. prototype = inherit (Super. prototype); var sub = new suber ("suber1"); var sub2 = new suber ("suber2"); console. log (sub. arr1); // I'm super suber1console. log (sub. show); // function () {alert (this. arr1);} console. log (sub. say); // function () {alert (this. arr1);} console. log (sub. show === sub2.show); // true; console. log (sub. say = sub2.say); // true;

Okay, so we can eliminate the disadvantages of the three methods. This can be used perfectly.

V. Copying attributes

We can write a copy function for copying.

Function extend (Super, suber) {suber = suber | |{}; for (var I in Super) {if (Super. hasOwnProperty (I) {suber [I] = Super [I] ;}} return suber;} var parent = {name: "dad", num: [1, 2, 3], say: function () {alert ("dad") ;}} var child = {age: 5, sex: "boy"}; child = extend (parent, child ); // The following test console. log (child);/* {age: 5, sex: "boy", name: "dad", num: [1, 2, 3], say: function () {alert ("dad") ;}} */console. log (child. say = parent. say); // trueconsole. log (child. num = parent. num); // true

If the replication succeeds, child successfully inherits some parent attributes, but the two tests later show that they are equal, which means they share the same Array and function, this can be a function, but there is a problem with the array. If a chiild changes the array, several arrays of inherited objects will also change, which will not work.
Why is this happening? In js, the object stores a pointer, and then this pointer points to this value. What we copy here actually points to the pointer value of this object, therefore, both the inherited object and the inherited object point to the same object. Next, let's take a look at how to use deep replication to solve this problem.

Deep copy object attributes:

function extenddeep(Super, suber){      var tostr = Object.prototype.toString, astr = "[object Array]";      suber = suber || {};      for(var i in Super){        if(Super.hasOwnProperty(i)){          if(typeof Super[i] === "object"){            suber[i] = (tostr.call(Super[i]) == astr) ? [] : {};            extenddeep(Super[i],suber[i]);          }else {            suber[i] = Super[i];          }        }      }      return suber;    }    var parent = {      name:"papa",      num:[1,2,3],      say:function(){alert("I'm father of my son!");}    }    var child = {      name:"jone",      sex:"boy",    }    var kid = extenddeep(parent, child);    console.log(kid);  // {name: "papa"                num: Array[3]                say: ()                sex: "boy"              // }    console.log(kid.say === parent.say); //true    console.log(kid.num === parent.num);  //false    console.log(kid.name); //papa

Well, the deep replication is complete, but it seems that the name is parent, which means that if the property of the inherited object and the property name of the inherited object are not processed, it will be replaced. Then we can do a bit of processing. First, declare an attribute and save the items in the parent. The rest is of course the child's own stuff. Finally, we can give the property to the child object.

6. Use the call and apply methods (borrow methods ).
This is how to reuse other objects through call and apply.

var one = {      name:"object",      say: function(greet){        return greet + ', ' + this.name;      }    }    var tow = {      name:"two"    }    one.say.call(tow, "hi");  //hi, two

This is borrowed. Okay, class.

Okay. Well, there are other things to watch. You can borrow a method that does not contain a table. You can assign a value to a method and use it as if nothing happened. Therefore, we should pay attention to the context when using the app. Let's take a look at the error-prone areas.

// When a value is assigned to a variable, the context changes var say = one. say; console. log (say ('hohoho'); // "hoho, undefined" // as the callback function, var yetother = {name: "yetother obj", method: function (callback) {return callback ("Hola") ;}} console. log (yetother. method (one. say); // "Hola ,"

What does Shenma mean? It's this. name is undefined, when one. when 'say 'is assigned to 'say', it actually stores the pointer to the function object. The variable 'say 'is obviously an attribute of the global variable, the actual context becomes windows when it runs, and the name becomes undefined at this time. The same is true for callback. return is the result of function execution. If we set windows. name = "windows" in advance, the result will be "hoho, windows" and "Hola, windows.

function bind(o, m){      return function(){        return m.apply(o, [].slice.call(arguments));      }    }    var othersay = bind(yetother, one.say);    othersay("Hola"); //"Hola, yetother obj"

Apply can be used to change the context of method execution, so we construct a function to implement such a function and implement context change by using method calls, in this way, the context is not what we expect.

// This section is copied directly. // 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 ('bonjobur'); // "Bonjour, another object" var twpolicy3 = one. say. bind (two, 'encoding'); console. log (twpolicy3 (); // "Enchant é, another object"

After the introduction, let's talk about your doubts. When there are methods in the inherited object in the copy attribute method, how can we copy them separately, after all, the method is not changed frequently. Please answer?

The following is the extend method of jQuery, which is reproduced. It seems that there is no special processing function, and the inheritance of the two functions is shared.

$. Extend source code

JQuery. extend = jQuery. fn. extend = function () {var options, name, src, copy, copyIsArray, clone, target = arguments [0] |{}, I = 1, length = arguments. length, deep = false; // Handle a deep copy situation // if the first parameter is of the boolean type, use the second parameter as target if (typeof target = "boolean") {deep = target; // skip the boolean and the target = arguments [I] |{}; // I ++ is used to determine I ++ for the sake of I === length ;} // Handle case when target is a string or something (possible in deep copy) // if the target is neither an object nor a method (for example, if you do not report an error but it is useless to extend the attribute methods and attributes of the basic type), modify target as a js object if (typeof target! = "Object "&&! JQuery. isFunction (target) {target ={};}// extend jQuery itself if only one argument is passed // if there is only one parameter, corrected the object as a JQuery function or JQuery object if (I = length) {target = this; // corrected the location of the target, the object I --;} for (; I <length; I ++) to be added to the target) {// Only deal with non-null/undefined values if (options = arguments [I])! = Null) {// Extend the base object for (name in options) {src = target [name]; copy = options [name]; // Prevent never-ending loop // if the target and copy objects are the same object, skip this step to Prevent cyclic references caused by the object referenced by your attributes, as a result, GC cannot recycle if (target = copy) {continue;} // Recurse if we're re merging plain objects or arrays // if deep is true, and the copy to be added to the target is the object to get the array if (deep & copy & (jQuery. isPlainObject (copy) | (copyIsArray = jQuery. isA Rray (copy) {if (copyIsArray) {copyIsArray = false; clone = src & jQuery. isArray (src )? Src: [];} else {clone = src & jQuery. isPlainObject (src )? Src: {};}// Never move original objects, clone them // very clever. It uses a recursion to achieve deep cloning of referenced objects, recursive return conditions are the basic types of attribute stone. The basic types are the target [name] = jQuery. extend (deep, clone, copy); // Don't bring in undefined values} else if (copy! = Undefined) {// clone target [name] = copy ;}}/return the modified object Return target ;};

The summary of the above javascript inheritance learning experience is all the content shared by the editor. I hope you can give us a reference and support for the help house.

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.