Introduction to the JS prototype chain-javascript tips-js tutorial

Source: Internet
Author: User
This article mainly introduces some information about the understanding of the JS prototype chain. If you need a friend, you can refer to the prototype chain to understand it. There are also a lot of online materials, when I can't sleep at night, I always like to read articles about prototype chains and closures on the Internet. The results are superb.

Don't get stuck with that bunch of terms. It doesn't really help you unless it turns your mind into a twist. Let's simply look at the prototype chain and think about code-independent things, such as human, demon, and demon.

1) a person is born by his mother, and a demon is born by his mother. Both the man and the demon are object instances, and the man and his mother are prototype. A prototype is also an object, called a prototype object.

2.

3) a person will record his/her information, so he/she can find his/her information, that is, he/she can find constructors through prototype objects.

4) A person can have many mothers, but these babies have only one mother. This is the uniqueness of the prototype.

5) people are also born by their mother. They find people by their mother, and then find people by their mother ......, This relationship is called the prototype chain.

6) The prototype chain is not infinite. When you keep searching for the prototype chain, you will find that the person is his mother ...... The prototype chain eventually points to null.

7) a person who gives birth to his mother will look like someone else. A demon born from his mother will have an ugly demon, which is called inheritance.

8) you inherit the color of your mother's skin, and your mother inherits the color of your mother's skin ......, This is the inheritance of the prototype chain.

9) If you don't have a home, your home refers to your mom's home. If you don't have a home, your home refers to your mother's home ...... This is the upstream search of the prototype chain.

10) You will inherit from your mother's appearance, but you can also dye, wash, and blow the hair. That is to say, the attributes of the object can be customized and will overwrite the inherited attributes.

11) although you have washed and blown your hair and dyed it yellow, you cannot change your mother's appearance. It doesn't matter if your mother's younger brother and sister were born with your yellow hair, that is to say, the properties of the prototype cannot be modified for the object instance.

12) If your family is burned by fire, that is to say, your mom's family and your younger brother's family are burned. This is the sharing of prototype attributes.

13) your mother's nickname azhen, the neighbor's aunt called you azhen, but your mother's hair was changed from rejoice to Queen Jin Mao, And the next big brother called you Prince Jin Mao. This is the dynamic nature of the prototype.

14) your mom loves beauty, and she ran to Korea for plastic shaping. She couldn't recognize it all the time. Even if your mom's hair is loose, her next-door neighbor still called you Prince Jin Mao. No one recognizes your mom. After the shaping, your mom has been re-built. This is the overall re-writing of the prototype.

Nima! That's enough for you! Don't BB! Show me the code!

Function Person (name) {this. name = name;} function Mother () {} Mother. prototype = {// Mother prototype age: 18, home: ['beijing', 'shanghai']}; Person. prototype = new Mother (); // The prototype of Person is Mother // You can view it using chrome debugging tools, provides the _ proto _ interface to view the prototype var p1 = new Person ('jack'); // p1: 'jack'; _ proto __: 18, ['beijing', 'shanghai'] var p2 = new Person ('mark'); // p2: 'mark'; _ proto __: 18, ['beijing ', 'shanghai'] p1.age = 20;/* The instance cannot change the prototype. The basic value attribute, just as you have nothing to do with your mom * Add a normal operation of the age attribute under the p1 instance, regardless of the prototype. Same as var o {}; o. age = 20. * P1: The following table contains multiple attributes, and _ proto _ is the same as Mother. prototype, and age = 18. * P2: only the attribute name ,__ proto _ and Mother. like prototype */p1.home [0] = 'shenzhen';/* share the reference type attribute in the prototype. Just as you burned your home, it burned your family's home, what if I had to worry about it? * P1: 'jack', 20; _ proto __: 18, ['shenzhen', 'shanghai'] * p2: 'mark'; _ proto __: 18, ['shenzhen', 'shanghai'] */p1.home = ['hangzhou', 'hangzhou'];/* is actually the same as p1.age = 20. In this case, var o {}; o. house = ['Big ', 'house'] * p1: 'jack', 20, ['hangzhou', 'hangzhou']; _ proto __: 18, ['shenzhen', 'shanghai'] * p2: 'mark'; _ proto __: 18, ['shenzhen', 'shanghai'] */delete p1.age; /* after the custom attribute is deleted, the original overwritten prototype value will repeat the day. Here is the upward search mechanism, so the following dynamics are available * p1: 'jack', ['hangzhou', 'hangzhou']; _ proto __: 18, ['shenzhen', 'shanghai'] * p2: 'mark'; _ proto __: 18, ['shenzhen', 'shanghai'] */Person. prototype. lastName = 'jin';/* rewrite the prototype and dynamically respond to the instance. As your mom is changing, the neighbors mentioned that you are the son of a popular lady * Note that here we rewrite the prototype of Person, that is, adding a lastName attribute to Mother, which is equivalent to Mother. lastName = 'jin' * the Mother is not changed here. prototype. The effects of changes to different levels are often very different. * P1: 'jack', ['hangzhou', 'hangzhou']; _ proto __: 'jin' ;__ proto __: 18, ['shenzhen ', 'shanghai'] * p2: 'mark'; _ proto __: 'jin' ;__ proto __: 18, ['shenzhen', 'shanghai'] */Person. prototype = {age: 28, address: {country: 'usa', city: 'Washington '}}; var p3 = new Person ('Obama');/* rewrite the prototype! At this time, the Person prototype has completely become a new object, that is, the Person has changed to a mother. * In this case, var a = 10; B = a; a = 20; c =. So B remains unchanged and becomes c, so p3 changes and has nothing to do with Mother. * P1: 'jack', ['hangzhou', 'hangzhou']; _ proto __: 'jin' ;__ proto __: 18, ['shenzhen ', 'shanghai'] * p2: 'mark'; _ proto __: 'jin' ;__ proto __: 18, ['shanghai', 'shanghai'] * p3: 'Obama ';__ proto __: 28 {country: 'USA', city: 'Washington '} */Mother. prototype. no = 9527;/* rewrite the prototype and dynamically respond to the instance. Just as your mom is changing to the latest version, the neighbors mentioned that you are talking about your grandmother. * Note: here we rewrite Mother. prototype And p1p2 will change, but the above p3 and Mother are irrelevant and will not affect him. * P1: 'jack', ['hangzhou', 'hangzhou']; _ proto __: 'jin' ;__ proto __: 18, ['shenzhen ', 'shanghai'], 9527 * p2: 'mark'; _ proto __: 'jin' ;__ proto __: 18, ['shanghai', 'shanghai'], 9527 * p3: 'Obama ';__ proto __: 28 {country: 'USA', city: 'Washington '} */Mother. prototype = {car: 2, holobby: ['run', 'walk ']}; var p4 = new Person ('Tony');/* rewrite the prototype! At this time, the Mother prototype has completely become a new object! * Since the Person and Mother mentioned above have been disconnected, the change of Mother does not affect the Person. * P4: 'Tony ';__ proto __: 28 {country: 'usa', city: 'Washington'} */Person. prototype = new Mother (); // bind var p5 = new Person ('luffy') again; // if you need to apply these changes at this time, then we need to re-bind the Person prototype to mother. // p5: 'luffy' ;__ proto __: 2, ['run ', 'row'] p1. _ proto __. _ proto __. _ proto __. _ proto _/null. Do you mean that the end of the prototype chain is not null? Mother. _ proto _/null. Do you mean that the end point of the prototype chain is not null?

Can I understand it after reading it?

Now let's talk about the differences between p1.age = 20, p1.home = ['hangzhou', 'hangzhou'] And p1.home [0] = 'shenzhen. P1.home [0] = 'shenzhen'; In summary, it is in the form of p1.object. method, p1.object. property.

P1.age = 20; p1.home = ['hangzhou', 'hangzhou, think about how we add attributes to a common object:

var obj = new Object();obj.name='xxx'; obj.num = [100, 200]; 

So I can understand it? The same.

So why does p1.home [0] = 'shenzhen' not create a home array attribute under p1 and set its first attribute to 'shenzhen? Let's forget this first. Think about the above obj object. If it is written as follows: var obj. name = 'xxx', obj. num = [100,200]. Can you get the expected result? Obviously, you cannot get anything except an error. Because obj is not defined yet, how can I add something to it? Similarly, the home in p1.home [0] is not defined under p1, so you cannot directly define home [0. If you want to create a home Array under p1, of course it is written as follows:

p1.home = []; p1.home[0] = 'Shenzhen'; 

Isn't that our most common method?

P1.home [0] = 'shenzhen' does not directly report an error because there is a search mechanism in the prototype chain. When p1.object is input, the search mechanism of the prototype chain is to first search for the corresponding value in the instance. If no value is found, it is found in the prototype, search for the previous prototype if it cannot be found ...... Till the end of the prototype chain, that is, if null is not found, an undefined is returned. When p1.home [0] is input, the search mechanism is the same. Search p1 to see if there are any properties and methods named home, and then search up one by one. Finally, we found the Mother prototype, so modifying it is equivalent to modifying the Mother prototype.

In a word, p1.home [0] = 'shenzhen' is equivalent to Mother. prototype. home [0] = 'shenzhen '.

From the above analysis, we can know that the main problem of prototype chain inheritance lies in the sharing of attributes. In many cases, we only want to share methods, but not attributes. Ideally, each instance should have its own attributes. Therefore, there are two ways to improve prototype inheritance:

1) Combination inheritance

Function Mother (age) {this. age = age; this. holobby = ['running', 'football']} Mother. prototype. showAge = function () {console. log (this. age) ;}; function Person (name, age) {Mother. call (this, age); // The second execution of this. name = name;} Person. prototype = new Mother (); // the first time the Person is executed. prototype. constructor = Person; Person. prototype. showName = function () {console. log (this. name);} var p1 = new Person ('jack', 20); p1.hoby. push ('bucketball '); // p1: 'jack'; _ proto __: 20, ['running ', 'football'] var p2 = new Person ('mark', 18); // p2: 'mark'; _ proto __: 18, ['running ', 'football']

The result is:

In the first execution, we get the Person. prototype. age = undefined, Person. prototype. holobby = ['running', 'football']. When the second execution is var p1 = new Person ('jack', 20), we get p1.age = 20, p1.hober = ['running', 'football']. After push, it becomes p1.hober = ['running', 'football', 'bucketball ']. In fact, it is easy to understand the changes of this. You can simply replace this with the result. If you feel like it is difficult to understand, try to discard the concept in your mind and execute the code from top to bottom as a browser. Will the result come out?

Through the second execution of the prototype constructor Mother (), we copied a prototype property in the object instance, so that the separation from the prototype property is achieved. If you are careful, you will find that the first call of Mother () seems to be useless. Can you not call it? Yes, there is the parasitic combined inheritance below.

2) parasitic combined inheritance

function object(o){function F(){}F.prototype = o;return new F();}function inheritPrototype(Person, Mother){var prototype = object(Mother.prototype); prototype.constructor = Person; Person.prototype = prototype; }function Mother (age) {this.age = age;this.hobby = ['running','football']}Mother.prototype.showAge = function () {console.log(this.age); };function Person (name, age) { Mother.call(this, age);this.name = name; }inheritPrototype(Person, Mother);Person.prototype.showName = function () {console.log(this.name);}var p1 = new Person('Jack', 20); p1.hobby.push('basketball');//p1:'Jack'; __proto__:20,['running','football']var p2 = new Person('Mark', 18); //p2:'Mark'; __proto__:18,['running','football'] 

The result is:

The prototype no longer has the age and holobby attributes. There are only two methods, which are exactly what we want!

The key point is in object (o). A temporary object is used here to cleverly avoid calling new Mother (), and then a new object instance with the prototype of o is returned, this completes the configuration of the prototype chain. That's because we cannot directly set Person. prototype = Mother. prototype.

Summary

-------------------------------------------------------------------------------

After talking about this, there is actually only one core: attribute sharing and independent control. When your object instance requires independent attributes, the essence of all practices is to create attributes in the object instance. If you don't think too much about it, You can directly define the attributes you need in Person to overwrite the attributes of the prototype. In short, when using prototype inheritance, you should pay special attention to the attributes in the prototype, because they all exist as a whole.

The following is a simple list of methods for creating objects in js. The most common method is the combination mode. You can skip to the end of the article and click like.

1) original mode

// 1. original mode: var person = {name: 'jack', age: 18, sayName: function () {alert (this. name) ;}}; // 1. original mode, Object constructor mode var person = new Object (); person. name = 'jack'; person. age = 18; person. sayName = function () {alert (this. name );};

Obviously, when we want to create a batch of person1, person2 ...... A lot of code is required each time, and senior copypaster cannot afford it! Then there is the batch production factory model.

2) Factory Model

// 2. factory mode, defines a function to create the Object function creatPerson (name, age) {var temp = new Object (); person. name = name; person. age = age; person. sayName = function () {alert (this. name) ;}; return temp ;}

The factory model is batch production, and simple calls can be used to enter the artificial intelligence model (such as pop-up ......). By specifying the name age, you can create a bunch of babies and release them. However, because it is a factory dark box operation, you cannot identify the type, human, or dog of the Object (instanceof testing is an Object ), in addition, an independent temp object should be created each time a person is created, and the code is bloated.

3) constructor

// 3. constructor mode: defines a constructor function Person (name, age) {this. name = name; this. age = age; this. sayName = function () {alert (this. name) ;}}var p1 = new Person ('jack', 18); // create a p1 object Person ('jack', 18 ); // attribute methods are all provided to the window object, window. name = 'jack', window. sayName () will output Jack

The constructor is similar to the constructor of classes in C ++ and JAVA, which is easy to understand. In addition, the Person can be used as the type recognition (instanceof testing is Person and Object ). However, all instances are still independent, and the methods of different instances are actually different functions. Let's forget the two words of the function here. We can understand sayName as an object. That is to say, the sayName of Zhang San and the sayName of Li Si are different, but obviously we want to share a sayName to save memory.

4) Prototype

// 4. prototype: directly defines the prototype attribute function Person () {} Person. prototype. name = 'jack'; Person. prototype. age = 18; Person. prototype. sayName = function () {alert (this. name) ;}; // 4. prototype mode: function Person () {} Person. prototype = {name: 'jack', age: 18, sayName: function () {alert (this. name) ;}}; var p1 = new Person (); // name = 'jack' var p2 = new Person (); // name = 'jack'

Note the sharing of prototype attributes and methods, that is, all instances only reference the property methods in the prototype. Any changes made in any part of the instance may cause changes to other instances.

5) hybrid mode (Construction + prototype)

// 5. prototype constructor combination mode, function Person (name, age) {this. name = name; this. age = age;} Person. prototype = {holobby: ['running', 'football']; sayName: function () {alert (this. name) ;}, sayAge: function () {alert (this. age) ;}}; var p1 = new Person ('jack', 20); // p1: 'jack', 20; _ proto __: ['running ', 'football'], sayName, sayAgevar p2 = new Person ('mark', 18); // p1: 'mark', 18 ;__ proto __: ['running ', 'football'], sayName, sayAge

The practice is to put the property methods that need to be independent into the constructor, and the shared part is put into the prototype. This can save the memory to the maximum extent and retain the independence of the object instance.

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.