A deep understanding of javascript prototype chain and inheritance, and a deep understanding of javascript

Source: Internet
Author: User
Tags prototype definition

A deep understanding of javascript prototype chain and inheritance, and a deep understanding of javascript

In the previous article, I introduced the concept of prototype and learned the relationship among the three friends in javascript: constructor, prototype object, and instance: every constructor has a "patron saint"-a prototype object. The prototype object also contains a "location" of the constructor, however, the instance has a "Crush" on the prototype object, and she also keeps the position of the prototype object in her mind.

Javascript itself is not an object-oriented language, but an object-based language. For those who are used to other OO languages, it is not suitable at first, because there is no "class" concept here, or the "class" and "instance" are not differentiated, let alone the "parent class" and "subclass. So what is the connection between this pile of objects in javascript?
Fortunately, javascript provided an implementation method of "inheritance" at the beginning of its design. Before learning about "inheritance", we should first understand the concept of prototype chain.

Prototype chain

We know that the prototype has a pointer to the constructor. What if we make the SubClass prototype object equal to the new SuperClass () of another type? In this case, the SubClass prototype object contains a pointer to the SuperClass prototype, and the SuperClass prototype also contains a pointer to the SuperClass constructor... In this way, a prototype chain is formed.

The 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!

Use prototype chain to implement inheritance

From the code above, we can see that SubClass inherits the attributes and methods of SuperClass. This inheritance is implemented by assigning the SuperClass instance to the SubClass prototype object, in this way, the SubClass prototype object is overwritten by an instance of SuperClass, and has all its attributes and methods. It also has a pointer to the SuperClass prototype object.

When using prototype chain to implement inheritance, we need to pay attention to the following points:

Note the constructor changes after inheritance. The sub constructor points to the SuperClass because the SubClass prototype points to the SuperClass prototype. When understanding the prototype chain, do not ignore the default Object at the end, which is why we can use the built-in methods of toString and other objects in all objects.

When the prototype chain is used to implement inheritance, the prototype method cannot be defined literally, because this will overwrite the prototype object (which was also introduced 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 = {// The prototype object is overwritten because the SuperClass attribute and method subSayWhat: function () {return this. subname + ": I'm a beautiful girl" ;}} var sub = new SubClass (); console. log (sub. sayWhat (); // TypeError: undefined is not a function

Instance sharing issues. When we explained the prototype and constructor, we once introduced that the prototype containing the reference type property will be shared by all instances. Similarly, the inherited prototype also shares the property of the reference type in the "parent class" prototype. After we modify the reference type attribute of the "parent class" through the prototype inheritance, all other instances inherited from this prototype will be affected, which is not only a waste of resources, but also a phenomenon we do not 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: add an element to the array. All instances inherited from the SuperClass will be affected. However, modifying the name attribute will not affect other instances because the array is of reference type, name is the basic type.
How can we solve the problem of instance sharing? Let's take a look...

Constructor stealing)

Just as we have introduced that prototype definition objects are rarely used separately, prototype chain is rarely used in actual development. To solve the Sharing Problem of reference types, javascript developers introduce the classic inheritance mode (also known as borrow constructor inheritance). The implementation of this mode is very simple, that is, to call a super-Type constructor in a subtype constructor. We need to use the call () or apply () functions provided by javascript. Let's look at the following example:

Function SuperClass () {this. name = "women"; this. bra = ["a", "B"];} function SubClass () {this. subname = "your sister"; // assign the SuperClass scope to the current constructor to inherit the 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); this statement means that the initialization of the SuperClass constructor is called in the SubClass instance (context) environment, in this way, each instance will have its own copy of the bra attribute, which does not affect each other.
However, this implementation method is still not perfect. Since constructor is introduced, we are also faced with the constructor problems mentioned in the previous article: if there is a method definition in the constructor, there is a separate Function reference for none of the instances. Our goal is to share this method, in addition, the methods defined in the super-type prototype cannot be called in the sub-type 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 prototype objects and constructor, you must already know the answer to this question. That is to follow the previous article's routine and use "Combination boxing "!

Combined inheritance

Combined inheritance is a combination of the advantages of the prototype chain and constructor to develop their respective strengths and combine them to implement inheritance. Simply put, the prototype chain is used to inherit attributes and methods, the constructor is used to inherit instance attributes. This not only solves the problem of instance attribute sharing, but also allows super-type attributes and methods to be inherited:

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 (); // The first call of SuperClass var sub1 = new SubClass (); console. log (sub1.sayWhat (); // hello

The combination inheritance method is also the most commonly used method for implementing inheritance in actual development. This can already meet your actual development needs, but there is no end to human pursuit of perfection, then, there will inevitably be people who are "nitpicking" this mode: You have called two super-type constructors in this mode! Twice... Are you sure you want to scale it up to one hundred times? How much is the performance loss?
The most powerful counterargument is to come up with a solution. Fortunately, developers have found the optimal solution to this problem:

Parasitic combined inheritance

Before introducing this inheritance method, we should first understand the concept of parasitic constructor. Parasitic constructor is similar to the factory model mentioned above. Its idea is to define a common function, this function is used to process object creation. After creation, this object is returned. This function is similar to a constructor, but the constructor does not return values:

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 parasitic inheritance is similar to that of parasitic constructor. It creates a "Factory" function that does not depend on a specific type to process the inheritance process of objects and then returns the inherited object instance, fortunately, we don't need to implement this by ourselves. Brother Douglas has already provided us with an implementation method:

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 a public function, and the instances of the passed objects are assigned to the prototype object of the constructor. The example of the constructor is returned, which is very simple but effective, isn't it? This method is called "original type inheritance" by future generations, and parasitic inheritance is implemented by enhancing the Custom Attributes of Objects Based on the original type:

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

The parasitic inheritance method is also faced with the problem of function reuse in the prototype. As a result, people began to build blocks again and came into being-parasitic combined inheritance, the purpose is to solve the problem of calling the parent Type constructor when specifying the child Type prototype, and at the same time, achieve maximum function reuse. The basic implementation method is as follows:

// The parameter is two constructor functions: inheritObj (sub, sup) {// implement instance inheritance and obtain a copy of the super-type var proto = object (sup. prototype); // re-specify the constructor attribute proto of the proto instance. constructor = sub; // assign the created object to the sub-type prototype 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 two super-type calls and saves SubClass. the prototype does not need any attributes, but also maintains the prototype chain. This really ends the inheritance journey, and this implementation method has become the most ideal inheritance implementation method! The controversy over the inheritance of javascript continues. Some people advocate OO, while others oppose the redundant efforts made in javascript to implement the features of OO. Let's take a look at it at least!


Javascript prototype inheritance

Shy2850 answers no questions
Add one point
The value in the form of p2.c in Javascript is first searched for whether the property c exists in the object p2. If any, the value c is directly returned. If no value exists, return to the prototype object of the class p2 to find the c attribute. If it is found, return. If it is not found, an error is returned.

So why do you want to change p2.c = 5 to p2.c. push (5:
P2.c = 5 is a value assignment operation, which is equivalent to adding a c attribute to object p2.
P2.c. push (5) First searches for the c attribute in the p2 object. If no c attribute is found, the c attribute of the prototype object is returned, and then the push method of the prototype Object c is called, add 5 to the array of the prototype object

Detailed explanation of javascript prototype chain inheritance requires detailed answers! A high reward. Let's take a look at js!

After learning, I have never used a class to inherit from a class. Currently, all the code written is simple settings of the prototype attribute.
After studying your code (as if you have seen it somewhere), you can simply set the prototype attribute in the core section:
Extend (absObj, sprPropty); // clazz. prototype = superclass. prototypeextend (absObj, constructor (sprPropty); // clazz. after adding a new property to prototype, you understand the prototype mechanism.
Reference: www.w3school.com.cn/..ng.asp
There is also a small problem. It is estimated that superclass will be called in the initialize method of the subclass. initialize. call (this, options); otherwise, the subclass will not have the attributes defined in the parent class initialize, so that they can be written to the clazz function:
Var clazz = function () {// call the constructor of the parent class, a bit like a java constructor. The super constructor must be placed at the top of the superclass & superclass. prototype. superclass & superclass. prototype. initialize. apply (this, arguments); // call the constructor of the subclass this. initialize. apply (this, arguments) ;};/** there is also a ** // if there is no parameter, directly return class: Dog blood, if clazz does not have a parameter, can it still run? What is clazz returned? if (arguments. length = 0) return clazz; // directly throw an exception. if (arguments. length = 0) throw new Error ("dog blood ");

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.