Those things that are inherited in JavaScript

Source: Internet
Author: User
Tags shallow copy
Introduction

JS is an object-oriented language, but in JS did not introduce the concept of class, before the special doubts in the JS inheritance mechanism in the end is how, has been learning JS inherited this piece after the Epiphany, then remember it.

If there is now a "human" constructor:

function Human () {    this. Type = ' human ';} 
There is also a "man" constructor:
function Mans (Name,age) {    this. Name = name;      this. Age = Age ;}
now what we want to achieve is to let this "man" Inherit "human".

Borrowing constructors

We can achieve the effect of a subtype inheriting a super-type by calling the super-type constructor inside the subtype. A function is a code object that executes in a particular environment, so a constructor can be executed on the newly created object either by call () or by apply ().

        function Man ("name, age") {            human.apply (this, arguments            ); this. Name = name;             this. Age = Age ;         }         var New Man (' Shanlei ');        Console.log (Man.type);         // Output: Human
in Code human.apply (this,arguments) This section of code is seconded with a super-type constructor, through the Apply function (or call () function), in fact, in the context of (will) the newly created man instance of the super-type constructor, This will execute all the object initialization code defined in the human () function on the man instance object, so that each instance of man will have its own copy of the Type property.

However, the use of constructors to inherit, it is inevitable that there are methods are defined in the constructor, can not implement the reuse of functions. And the methods defined in the prototype of the superclass are not visible to the subtypes, and the result is that all types are inherited using constructors, so there is less case for using constructors alone.

Through the prototype chain

The definition mechanism of prototype chain I've already mentioned it in JavaScript's original chain, after all, the implementation of inheritance through the prototype chain is done through the prototype attribute.

If man's prototype points to an instance of human, then the man prototype object will include a pointer to human, and all instances of man can inherit human.

        function Mans (Name,age) {            this. Name = name;              this. Age = Age ;        }         New Human ();         = Man ;         var New Man (' Shalei ');        Console.log (man.type);

We know in fact that the prototype property is essentially a pointer to a function object, and we change the prototype property to point to an instance of human.

Man.prototype.constructor = man;
we all know that any prototype object has a constructor property, and the constructor property points to its constructor, that is, if the prototype point of the man is not changed, So Man.prototype.constructor is pointing to man. More importantly, each instance also has a constructor property, and the constructor property of the instance calls prototype constructor by default, namely:
Console.log (Man1.constructor = = Man.prototype.constructor); // Output: True
so think about it. When you finish Man.prototype = new Human (), all the man instances point to the Human property, which is:
Console.log (Man1.constructor = = Human); // Output: True
This can lead to the disruption of the prototype chain, which means that the prototype chain will be interrupted, so we have to correct it manually.

We changed the point of the man's prototype and made him equal to a human instance object. That

Man.prototype.constructor = man;
This is a very important step, if we replace the prototype object in the code, then in order not to break the prototype chain, the next step is to correct the prototype constructor property, so that the property refers back to the original constructor.

Composite inheritance (pseudo-classic inheritance)

The whole idea of combinatorial inheritance is to use both the prototype chain and the borrowing constructor to take the advantage of both. The idea is to use the prototype chain to implement the inheritance of prototype properties and methods, and to borrow constructors to implement inheritance of instance properties. The benefit of this is that the reuse of the function is achieved, while ensuring that each property has its own properties.

Then the above allows "man" to inherit "human" can be achieved by combining inheritance:

Human.prototype.go =function() {Console.log (' running! '); }        functionMan (name, age) {human.apply ( This, arguments);  This. Name =name;  This. Age =Age ; } Man.prototype=NewHuman (); Man.prototype.constructor=Man ; varMan1 =NewMan (' Shanlei ', 20);        Console.log (Man1.type); Man1.type= ' Man ';        Console.log (Man1.type);        Console.log (Man1.name);        Console.log (Man1.age); varMan2 =NewMan (' Zhangkai ', 18);        Console.log (Man2.type);        Console.log (Man2.name);        Console.log (Man2.age); Man2.go ();

The output is as follows:

Human Manshanleihuman Zhangkai-running!
Prototype inheritance

What if the inherited object is not a constructor? We have no way to use the borrowed constructor for inheritance, so we can use the prototype inheritance.

This inheritance model was proposed by Douglas Kest Rockford. Prototype inheritance does not use a strictly constructed constructor. Instead, prototypes can be used to create new objects on existing objects, while avoiding the creation of custom types. So Douglas Kest Rockford gives a function:

        function Object (o) {            function  F () {}            = o;             return New F ();        }

We can create a new temporary object to hold all the properties and methods on the superclass to give the subtype inheritance. And this is what this function is going to do.

A temporary constructor is created inside the object function, then the incoming object is used as a prototype of the constructor, and a new instance of the temporary type is returned. It's essentially an object that makes a shallow copy of the incoming object.

Now there is a "man" object:

        var man = {            ' Shanlei ', age            : $        }
There is also a "human" object:
        var human = {            type:' Human '        }
now I want this man to inherit the human, that is to say, "men", he is a "human".

It is important to note that these two objects are now normal objects, not constructors, so we cannot use the methods above.

We can inherit through the prototype, as in the following example:

 var  human = {type:  ' Human ' 
  
   }  
   function  
    object (o) { 
   function  
    F () {}            F.prototype  =
    o;  
   return  
   new         
    F ();         
   var  ano_man =
    object (human);        Ano_man.name  = ' Shanlei ' 
   ;        Ano_man.age  = 20
   ; Console.log (Ano_man.type);  
  
prototype inheritance requires that an object be used as the basis for another object, and if so, simply pass it to the object function and then modify the resulting object as needed. In the example above, the object function returns a new object with human as its prototype, so its prototype contains a primitive type value attribute.

In ECMAScript, the prototype inheritance is regulated by the function object.create (), which receives two parameters, one for the new object prototype, and the second for the object that defines the additional properties for the new object, and in the case of passing in a parameter, Object.create ( ) is the same as the above object () function.

Copy inheritance

We can think about it. In fact, the meaning of inheritance is that the subtype takes all the properties and methods of the superclass and puts them on themselves. Then we can copy all the properties and methods of the super-type to the subtype, thus implementing the inheritance.

Shallow copy

We can implement a method that passes a super-type object to the method, and then adds the object's properties to the subtype and returns it with the following code:

        function Extendcopy (val) {            var c = [];              for (var in val) {                = val[i];            }             = val;             return c;        }

Specific use can be:

        var ano_man = extendcopy (human);         = ' Shanlei ';        Console.log (ano_man.type);

The use method is similar to the prototype inheritance described above. However, there is a big problem with implementing inheritance, that is, when the object's property is a reference type value (array, object, etc.), during the copy process, the child object obtains only one memory address, not the real copy of the property.

Deep copy

We can make deep copies on the basis of a shallow copy. We know that when copying a primitive type value is a new area in memory that is used to copy the storage of object properties, so we just have to recursively call the shallow copy.

    function deepcopy (P, c) {     var c = C | |  {};      for (varin  p) {          if (typeof p[i] = = = ' object ') {    = (P[i].constructor = = = Array)?         [] : {};    Deepcopy (P[i], c[i]);     Else      {    = P[i];    }    }        return  C; }

Using the same method as a shallow copy, this is not an example.

Parasitic inheritance

The idea of parasitic inheritance is to create a function that encapsulates the inheritance process, to augment the object in some way inside the function, and finally to return the object to the real thing that it did all the work. Or an example of the implementation of inheritance between the man and human two objects above:

function Createanother (original) {    var clone = Object (original);   // Create a new object    by calling a function function () {       // in some way to enhance the object        alert ("HI");    };     return clone;                  // return this object }
when used:
var clone = createanother (human); Clone.sayhi ();

In cases where the primary implementation object is a custom type rather than a constructor, parasitic inheritance is a useful inheritance pattern in which the object function used is not required, and any function that implements the function can do so.

Parasitic combined inheritance

Combinatorial inheritance is a very common inheritance pattern in JS, but there is a problem with this way of implementing inheritance, that is, in any case, the two-time super-type constructor will be called. Once, when creating a prototype of a subtype, the second time is inside the subtype constructor. The subtype eventually contains all the instance properties of the superclass object, but we have to override those properties when we call the subtype constructor. This can cause excessive memory loss in cases where inheritance is very frequent. This time, we can use parasitic combined inheritance!

Parasitic combined inheritance, is to borrow the constructor to inherit the property, through the prototype chain of the hybrid form to inherit the method. The idea is that you don't have to call a super-type constructor to specify a prototype of a subtype, all we need is a copy of the super-type prototype, essentially, using parasitic inheritance to inherit the super-type prototype, and then assign the result to the prototype of the subtype.

The basic pattern is as follows:

        function Inheritprototype (subtype, supertype) {            var prototype = object (Supertype.prototype);   // Creating Objects            Prototype.constructor = subtype;               // Enhanced Objects            Subtype.prototype = prototype;                 // Specify object        }
the function receives two parameters: a subtype constructor and a superclass constructor. Inside the function, the first step is to create a copy of the superclass prototype object. The second step is to add the constructor property to the replica created to compensate for the loss of the default constructor property due to rewriting the prototype. The final step copies the newly created copy object to the prototype of the subtype.

Let's go back to the first question: there is a "man" constructor and a "human" constructor, and I want men to inherit humans now!

        functionHuman () { This. Type = ' human '; } Human.prototype.sayHi=function() {Console.log (' Hi '); }        functionMan (name,age) {human.apply ( This, arguments);  This. Name =name;  This. Age =Age ;        } Inheritprototype (man, Human); varMan =NewMan (' Shalei ', 20); Console.log (Man.type) Man.sayhi ();

Parasitic combined inheritance is the most ideal inheritance paradigm for reference types!

Above ~

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.