Deep understanding of JavaScript prototype chain and inheritance _javascript techniques

Source: Internet
Author: User
Tags object object prototype definition

In the previous article, we introduced the concept of prototypes, learn about the relationships between a constructor, a prototype object, and an instance of three good friends in JavaScript: each constructor has a "Guardian God"--the prototype object, the prototype object also has a constructor in mind, "position", two lovers, But the example but "secretly love" the prototype object, she also retained in the heart of a prototype object position.

JavaScript itself is not an object-oriented language, but an object-based language, for those who are accustomed to other OO languages, at first it is not appropriate, because there is no "class" concept, or "class" and "instance" are not differentiated, let alone the "parent", "subclass" points. So how does this stack of objects in JavaScript relate?
Fortunately, JavaScript at the beginning of design provides the "inheritance" implementation, before understanding "inheritance", we now first understand the concept of the prototype chain.

Prototype chain

We know that prototypes have a pointer to a constructor, what if we let the subclass prototype object equal another type of instance new superclass ()? At this point, the subclass prototype object contains a pointer to the superclass prototype, and the superclass prototype also contains a pointer to the superclass constructor ... This layer of progressive, formed a prototype chain.

The specific code is as follows:

  Function superclass () {
    this.name = "Women"
  }
  SuperClass.prototype.sayWhat = function () {
    return THIS.name + ": I ' m a girl!";
  }
  function Subclass () {
    this.subname = "Your Sister";
  }
  Subclass.prototype = new Superclass ();
  SubClass.prototype.subSayWhat = function () {return
    this.subname + ": I ' m a beautiful Girl";
  }
  var sub = new subclass ();
  Console.log (Sub.saywhat ());//women:i ' m a girl!

Using a prototype chain to implement inheritance

As you can see from the code above, subclass inherits superclass's properties and methods, which are implemented by assigning superclass instances to subclass prototype objects. This subclass prototype object is overwritten by an instance of superclass, has all of its properties and methods, and also has a pointer to the superclass prototype object.

There are some areas that need our attention when using the prototype chain to implement inheritance:

Notice the change of constructor after inheritance. The constructor point of the sub here is superclass, because subclass's prototype points to the superclass prototype. When you understand the prototype chain, do not ignore the end and the default object object, which is why we can use the object in all objects built-in methods such as ToString.

When you implement inheritance through a prototype chain, you cannot define a prototype method with a literal, because it overrides the prototype object (described in the previous article):

  Function superclass () {
    this.name = "Women"
  }
  SuperClass.prototype.sayWhat = function () {
    return THIS.name + ": I ' m a girl!";
  }
  function Subclass () {
    this.subname = "Your Sister";
  }
  Subclass.prototype = new Superclass ();
  Subclass.prototype = {//Here the prototype object is overwritten because the superclass properties and methods cannot be inherited
    Subsaywhat:function () {return
      this.subname + ": I" M a beautiful Girl ";
    }
  }
  var sub = new subclass ();
  Console.log (Sub.saywhat ());//typeerror:undefined is not a function

An instance share problem. When you explain the prototypes and constructors earlier, we have described that a prototype containing a reference type attribute will be shared by all instances, and similarly, the attributes of the reference type in the "parent class" prototype are shared by our inherited prototypes, and when we inherit the reference type attribute of the "parent class" through the prototype inheritance, All other instances that inherit from the prototype are affected, which is not only a waste of resources, but a phenomenon we don't want to see:

  Function superclass () {
    this.name = "Women";
    This.bra = ["A", "B"];
  }
  function Subclass () {
    this.subname = "Your Sister";
  }
  Subclass.prototype = new Superclass ();
  var sub1 = new Subclass ();
  Sub1.name = "man";
  Sub1.bra.push ("C");
  Console.log (sub1.name);//man
  Console.log (Sub1.bra);//["A", "B", "C"]
  var sub2 = new Subclass ();
  Console.log (sub1.name);//woman
  Console.log (Sub2.bra);//["A", "B", "C"]

Note: Adding an element to the array here, all instances inherited from superclass are affected, but modifying the Name property does not affect other instances, because the array is a reference type, and name is the base type.
How do you solve the problem of instance sharing? We went on to look down ...

Classic inheritance (constructor stealing)

As we have described rarely using a prototype definition object alone, we rarely use the prototype chain alone in actual development, in order to solve the shared problem of reference types, JavaScript developers introduce classic inheritance patterns (also known as borrowed constructor inheritance), Its implementation is simply to call the superclass constructor in the subtype constructor. We need to use the call () or apply () function provided by JavaScript, and we'll look at the example:

Function superclass () {
  this.name = "Women";
  This.bra = ["A", "B"];
}
function Subclass () {
  this.subname = "Your Sister";
  Assigns the superclass scope to the current constructor, implementing the Inheritance
  Superclass.call (this);

var sub1 = new Subclass ();
Sub1.bra.push ("C");
Console.log (Sub1.bra);//["A", "B", "C"]
var sub2 = new Subclass ();
Console.log (Sub2.bra);//["A", "B"]

Superclass.call (this) means that the initialization of the superclass constructor is invoked in the subclass instance (context) environment, so that each instance has its own copy of the bra attribute and does not have an impact.
However, such implementations are still not perfect, and since the introduction of constructors, we also face the problem of the constructors mentioned in the previous article: if there is a method definition in the constructor, then there is a separate function reference for none of the instances. Our goal is actually to share this method, and the methods we define in the superclass prototype are not callable in the subtype instance:

  Function superclass () {
    this.name = "Women";
    This.bra = ["A", "B"];
  }
  SuperClass.prototype.sayWhat = function () {
    console.log ("Hello");
  }
  function Subclass () {
    this.subname = "Your Sister";
    Superclass.call (this);
  }  
  var sub1 = new Subclass ();
  Console.log (Sub1.saywhat ());//typeerror:undefined is not a function

If you have read the previous article about the prototype object and the constructor, presumably you already know the answer to the problem, that is, the use of the previous routine, using the "combination of boxing"!

Modular inheritance

Modular inheritance is the combination of prototype chain and the advantages of the constructor, issued their own expertise, combined to achieve the inheritance of a way, simply using the prototype chain to inherit the properties and methods, using the borrowed constructor to implement the inheritance of instance properties, so that both solve the problem of sharing instance properties, Also lets you inherit the properties and methods of the superclass:

  Function superclass () {
    this.name = "Women";
    This.bra = ["A", "B"];
  }
  SuperClass.prototype.sayWhat = function () {
    console.log ("Hello");
  }
  function Subclass () {
    this.subname = "Your Sister";
    Superclass.call (this);       The second call to superclass
  }
  Subclass.prototype = new Superclass ();////First Call superclass
  var sub1 = new Subclass ();
  Console.log (Sub1.saywhat ());//hello

The method of combining inheritance is also the most common way to implement inheritance in actual development, this has been able to meet your actual development needs, but the pursuit of perfection is endless, then, there will inevitably be someone to this model "nit-picking": you this pattern called two times the superclass constructor Yes! Two times Yes ... Do you build, how much performance loss is this magnified 100 times times?
The most powerful retort is to come up with a solution, but the developer finds the best solution to the problem:

Parasitic Modular Inheritance

Before introducing this inheritance approach, we first understand the concept of the parasitic constructor, which resembles the factory pattern mentioned earlier, and its idea is to define a common function that is designed to handle the creation of objects, which, when created, return the object, a function much like a constructor, However, constructors do not return a value:

function Gf (name,bra) {
  var obj = new Object ();
  Obj.name = name;
  Obj.bra = bra;
  Obj.saywhat = function () {
    console.log (this.name);
  }
  return obj;
}

var GF1 = new Gf ("Bingbing", "C + +");
Console.log (Gf1.saywhat ());//bingbing

The implementation of a parasitic inheritance is similar to a parasitic constructor, create a "factory" function that does not depend on a specific type to handle the inheritance process of an object, and then return the inherited object instance, which, fortunately, does not need to be implemented by ourselves, has already been provided by Doug (Douglas) with a way to achieve it:

function object (obj) {
  function F () {}
  f.prototype = obj;
  return new F ();
}
var superclass = {
  name: "Bingbing",
  bra: "C + +"
}
var subclass = object (superclass);
Console.log (subclass.name);//bingbing

A simple constructor is provided in the public function, and then the instance that is passed in the object is given to the stereotype object of the constructor, and finally the instance of the constructor is returned, which is simple, but the effect is very good, isn't it? This method is called "Archetypal inheritance" by posterity, and parasitic inheritance is implemented on a prototype basis by enhancing the custom attributes of the object:

function Buildobj (obj) {
  var o = object (obj);
  O.saywhat = function () {
    console.log ("Hello");
  }
  return o;
}
var superclass = {
  name: "Bingbing",
  bra: "C + +"
}
var gf = buildobj (superclass);
Gf.saywhat ();//hello

Parasitic inheritance is also faced with the problem of function reuse in the prototype, so people began to spell the building blocks, was born-parasitic modular inheritance, the purpose is to solve in the specified subtype prototype when the problem of calling the parent type constructor, at the same time, to achieve the maximum reuse of functions. Based on the above basic implementation methods are as follows:

parameter is two constructor function
inheritobj (sub,sup) {
  //Implementation instance inheritance, get a copy of the super type
  var proto = object (sup.prototype);
  Re-specify the constructor attribute of the proto instance
  Proto.constructor = sub;
  To assign a created object to a subtype
  sub.prototype = proto;
Function superclass () {
  this.name = "Women";
  This.bra = ["A", "B"];
}
SuperClass.prototype.sayWhat = function () {
  console.log ("Hello");
}

function Subclass () {
  this.subname = "Your Sister";
  Superclass.call (this);
}
Inheritobj (subclass,superclass);
var sub1 = new Subclass ();
Console.log (Sub1.saywhat ()); Hello


This implementation avoids the super type of two calls, but also eliminates the subclass.prototype of unnecessary attributes, but also maintain the prototype chain, to truly end the journey of inheritance, this implementation has become the most ideal way to inherit implementation! The controversy over the succession of JavaScript continues, with some advocating oo, and some are opposed to doing extra work in JavaScript to achieve OO features, or at least get a little deeper!

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.