Prototypes and prototype objects (__PROTO__ and prototype) go

Source: Internet
Author: User
Tags hasownproperty

After seeing it, I finally got a deeper understanding of the archetype, the girl who shared it, the original link: Understanding JavaScript
Prototype

I do not like, is to tell the prototype when the class is compared, so I will not say so. But I did talk about constructor functions, which are more or less in common with classes. My advice: Forget about the class. There are many views that the proliferation of "class" is an object-oriented over-development, is a sad, so many developers almost the object-oriented and the class is an equal sign. Before learning to prototype, I ask you to remember and taste this sentence:

The essence of object-oriented design is the word "abstract" , which is a means of implementing entity abstraction, but not the only one.

prototypeAnd __proto__

Declare beforehand: Never, never use attributes in real code __proto__ , and use it purely for research in this article! Soon we will talk about its substitutes, sorry please patience.

In JavaScript, the function is the object (after learning this one, you might want to look at how the function becomes an object?). ), object, no surprises there will be attributes (the method is also a property), and then no accident prototype is a property of the function, and finally no unexpected prototype property is an object. Look, what a logical thing to do:

function foo () {}foo.prototype;    What do you want to see in there?

  

Well, what's the prototype use? Well, if you use the function as a function, it's useless. However, if you use the function as a constructor, the newly generated object will have direct access to prototype the properties in the object.

to act as a constructor, it is customary to capitalize the first letter function Foo () {}var f = new Foo (); f.constructor;    function Foo () {}

  

Think about f where the constructor attributes come from? If you want to not understand, please use console.dir(Foo.prototype) a probe.

This illustrates a problem:

The prototype property of a function is not for the function itself, but for the object created by the constructor.

The confusing thing is that a prototype property exists Foo inside a function object, so Foo how is the instance object created f to access it prototype ? Is it by copying prototype objects? Then we continue to see the above code:

f.__proto__;                      Foo {}foo.prototype;                    Foo {}f.__proto__ = = = Foo.prototype;    True

  

Oh, it's not a copy, it's a __proto__ property called the object that points to the constructor prototype .

That's right! This is the essence of the prototype mechanism, so let's summarize all the details (including the underlying image):

    1. function has prototype properties, but the function does not use it itself
    2. A function can create a new object when it acts as a constructor, which requires new the mates of the operator. How it works I've done most of the elaboration in the first article
    3. What I haven't mentioned is that new when you create a new object, you give the new object a property that points to the constructor prototype . This new property is called in some browser environments.__proto__
    4. When accessing an object's properties (including methods), first find out if the object itself has this property, if it does not find its prototype (that is __proto__ , pointing to the prototype object), if you have not yet found a prototype prototype ( prototype also has its own __proto__ , pointing to a higher level of prototypeobject), and so on until it has been found Object

OK, the 4th of the above is actually the JavaScript object property lookup mechanism. Thus:

The meaning of a prototype is to provide a direction for the object's property lookup mechanism, or a route.

An object that has many properties, one of which points to the prototype property of another object, and a property that points to the prototype property of another object. It is like a chain with a ring, and from any point in the chain to find out, and finally can find the starting point of the chain, that is Object , we also call this mechanism: prototype chain .

Now, I want to unify the terminology used (at least within the scope of this article):

    • Properties of a function prototype : we call it a prototype attribute or prototype object
    • Object __proto__ Properties: We call it prototypes .

For example:

    • FooThe prototype attribute (or prototype object) =Foo.prototype
    • fThe prototype =f.__proto__

The reason for unifying terminology is that, although Foo.prototype f.__proto__ it is equivalent, it is prototype not the __proto__ same. When considering a fixed object, it prototype is used below the prototype chain, and it points to the __proto__ top of the prototype chain, so once we say "prototype attribute" or "prototype object", it implies that it is for its descendants, and that "prototype" is to imply that it was inherited from its parents.

In other words: The object's prototype property or prototype object is not for its own use, and the object's prototype can be used directly.

__proto__The problem

Since __proto__ you can access the prototype of an object, why is it forbidden to use it in practice?

This is a design error, resulting in __proto__ properties that can be modified, and means that JavaScript's property lookup mechanism is thus "paralyzed", so it is strongly not recommended to use it.

If you really want to access its prototype through an object, ES5 provides a new method:

Object.getprototypeof (f)    //Foo {}

  

This is safe, although use with ease. Given the compatibility issues of the low-version browsers, you can use the Es5-shim

The difference between the own property and the prototype attribute

Because the object's prototype is a reference rather than an assignment, changing the properties of the prototype immediately affects all instance objects. This feature is ideal for defining an instance method for an object:

function person (name) {    this.name = name;} Person.prototype.greeting = function () {    return "Hello, my name is" + this.name;}; var p1 = new Person ("Zhang San"), var p2 = new Person ("John Doe");p 1.greeting ();    Hello, my name is Zhang San p2.greeting ();    Hello, my name John Doe/* Change the behavior of the instance method: */person.prototype.greeting = function () {    return "Hello, my name is" + THIS.name + ", nice to meet you! ";};/ * Observe its effect: */p1.greeting ();    Hello, my name is Zhang San, nice to meet you! P2.greeting ();    Hello, my name is John Doe, nice to meet you!

  

However, changing the own property is different, it only affects the newly created instance object, and then the following example:

function person (name) {    this.name = "Superman";} /* Does not affect an existing instance object */p1.greeting ();    Hello, my name is Zhang San, nice to meet you! /* Only affects newly created instance objects */var p3 = new Person ("Harry");p 3.greeting ();    Hello, my name is Superman, nice to meet you!

  

This example seems a bit unreasonable and useless, but its spirit is that in the real world, the behavior of complex objects may be rewritten according to the circumstances, but we do not want to change the object's internal state, or we will implement inheritance to override some of the behavior of the parent object without directing the same parts. In these cases, prototypes give us the greatest degree of flexibility.

How do we know if a property is self-contained or a prototype? On the Code ~

P1.hasownproperty ("name");        Truep1.hasownproperty ("greeting");    Falsep1.constructor.prototype.hasOwnProperty ("greeting");     Trueobject.getprototypeof (p1). hasOwnProperty ("greeting");    True

  

The code is so simple that you don't have to explain it over and over and notice that the last two sentences are actually equivalent.

Be careful constructor

Just this code: p1.constructor.prototype.hasOwnProperty("greeting"); , actually implies an interesting question.

Object has p1 access to its own constructor, thanks to a prototype that provides properties for it constructor . Then, through the constructor property and in turn access to the prototype object, which seems to be a circle, we have to experiment:

P1.constructor = = = P1.constructor.prototype.constructor;    Truep1.constructor = = = P1.constructor.prototype.constructor.prototype.constructor;    True

  

It's true! But we didn't study this for fun.

Although we say that changing the properties of a prototype object will immediately act on all instance objects , if you completely overwrite the prototype object, things get weird: (Read the next example, just one sentence to verify your mind)

function person (name) {    this.name = name;} var p1 = new Person ("Zhang San"); Person.prototype.greeting = function () {    return "Hello, my name is" + this.name;}; P1.name;                      Zhang San P1.greeting ();                Hello, my name zhang san p1.constructor = = = person;    true/* so far good, but ... */person.prototype = {    say:function () {        return "Hello, my name is" + THIS.name;    }}; P1.say ();                    Typeerror:object #<person> has no method ' say ' P1.constructor.prototype;    Object {say:function}

  

Uh? Is Person there a method in the prototype attribute say ? Is the prototype object not immediately effective?

Prototype inheritance

If only to create an object, the role of the prototype can not be fully played out. We will further utilize the features of prototypes and prototype chains to extend our code to implement prototype-based inheritance.

Prototype inheritance is a very large topic range, and slowly you will find that although prototype inheritance does not seem to be as structured as the class inheritance (relative), it is more flexible. Whether it is single inheritance or multiple inheritance, even Mixin and other inherited ways that even the name can not be said, prototype inheritance has a way to achieve, and often more than one way.

But let's start with a simple first:

function person () {    this.klass = ' Human ';} Person.prototype.toString = function () {    return this.klass;}; Person.prototype.greeting = function () {    return ' Hello everyone, I call ' + THIS.name + ', I am a ' + This.klass + '. ‘;}; function Programmer (name) {    this.name = name;    This.klass = ' Programmer ';} Programmer.prototype = new Person (); Programmer.prototype.constructor = Programmer;

  

This is a very good example, and it reveals the following points to us:

var someone = new Programmer (' Zhang San '); someone.name;          Zhang San Someone.tostring ();    Programmer someone.greeting ();    Hello everyone, my name is Zhang San, I am a programmer.

  

Let me go through it:

    1. The second-to-last line, new Person() creates an object, and assigns it to Programmer.prototype Person the instance object that the constructor's prototype property becomes.
    2. Because the Person object has a overridden toString() method, and this method returns the properties of the host object klass , we can Programmer define a greeting() method and use inheritance in it toString() .
    3. When an someone object invokes a toString() method, this it points to itself, so it can output 程序员 instead 人类 .

Not yet, keep looking:

Because Programmer.prototype.constructor = Programmer; We can get: someone.constructor = = = Programmer;    true//These results embody the meaning of "chained" prototype inheritance someone instanceof Programmer;         true someone instanceof person;             True someone instanceof Object;             True

  

Method overloading

The above example has actually implemented the toString() overloading of the method (the ancestor of this method Object.prototype ), and in the same spirit, the sub-constructors we write ourselves can also overload the methods provided by the parent constructor through the prototype properties:

Programmer.prototype.toString = function () {    return this.klass + "(Code Farm)";} var codingfarmer = new Programmer ("Zhang San"); codingfarmer.greeting ();    Hello everyone, my name is Zhang San, I am a programmer (yard farm).

  

The contradiction between property lookup and method overloading

The students who are mentally active may already be thinking:

Why do you have to assign an instance of the parent class to the prototype property of the subclass, rather than using the parent class's prototype property directly?

Good question! The idea is very reasonable, and so we can reduce the number of attribute lookups, because when we look up, we skip the parent instance __proto__ and find it directly (as in the example above) Person.prototype .

But the reason for not doing so is simple, if you do:

Programmer.prototype = Person.prototype;

Since Javascript is a reference assignment, the two attributes at both ends of the equals sign point to the same object, so once you overload the method in the subclass, the method with the parent class changes, which loses the meaning of overloading. So you can do this only when you're sure you don't need an overload.

Prototypes and prototype objects (__PROTO__ and prototype) go

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.