__proto__ VS. prototype in JavaScript

后端 未结 30 1944
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-21 06:14

This figure again shows that every object has a prototype. Constructor function Foo also has its own __proto__ which is Function.prototype, a

相关标签:
30条回答
  • 2020-11-21 06:47

    I happen to be learning prototype from You Don't Know JS: this & Object Prototypes, which is a wonderful book to understand the design underneath and clarify so many misconceptions (that's why I'm trying to avoid using inheritance and things like instanceof).

    But I have the same question as people asked here. Several answers are really helpful and enlightening. I'd also love to share my understandings.


    What is a prototype?

    Objects in JavaScript have an internal property, denoted in the specification as[[Prototype]], which is simply a reference to another object. Almost all objects are given a non-nullvalue for this property, at the time of their creation.

    How to get an object's prototype?

    via __proto__or Object.getPrototypeOf

    var a = { name: "wendi" };
    a.__proto__ === Object.prototype // true
    Object.getPrototypeOf(a) === Object.prototype // true
    
    function Foo() {};
    var b = new Foo();
    b.__proto__ === Foo.prototype
    b.__proto__.__proto__ === Object.prototype
    

    What is the prototype ?

    prototype is an object automatically created as a special property of a function, which is used to establish the delegation (inheritance) chain, aka prototype chain.

    When we create a function a, prototype is automatically created as a special property on a and saves the function code on as the constructor on prototype.

    function Foo() {};
    Foo.prototype // Object {constructor: function}
    Foo.prototype.constructor === Foo // true
    

    I'd love to consider this property as the place to store the properties (including methods) of a function object. That's also the reason why utility functions in JS are defined like Array.prototype.forEach() , Function.prototype.bind(), Object.prototype.toString().

    Why to emphasize the property of a function?

    {}.prototype // undefined;
    (function(){}).prototype // Object {constructor: function}
    
    // The example above shows object does not have the prototype property.
    // But we have Object.prototype, which implies an interesting fact that
    typeof Object === "function"
    var obj = new Object();
    

    So, Arary, Function, Objectare all functions. I should admit that this refreshes my impression on JS. I know functions are first-class citizen in JS but it seems that it is built on functions.

    What's the difference between __proto__ and prototype?

    __proto__a reference works on every object to refer to its [[Prototype]]property.

    prototype is an object automatically created as a special property of a function, which is used to store the properties (including methods) of a function object.

    With these two, we could mentally map out the prototype chain. Like this picture illustrates:

    function Foo() {}
    var b = new Foo();
    
    b.__proto__ === Foo.prototype // true
    Foo.__proto__ === Function.prototype // true
    Function.prototype.__proto__ === Object.prototype // true
    
    0 讨论(0)
  • 2020-11-21 06:47

    This is a very important question relevant to anyone who wants to understand prototypical inheritance. From what I understand, prototype is assigned by default when an object is created with new from a function because Function has prototype object by definition:

    function protofoo(){
    }
    var protofoo1 = new protofoo();
    console.log(protofoo.prototype.toString()); //[object Object]
    

    When we create an ordinary object without new, ie explicitly from a function, it doesn't have prototype but it has an empty proto which can be assigned a prototype.

    var foo={
      check: 10
    };
    console.log(foo.__proto__); // empty
    console.log(bar.prototype); //  TypeError
    foo.__proto__ = protofoo1; // assigned
    console.log(foo.__proto__); //protofoo
    

    We can use Object.create to link an object explicitly.

    // we can create `bar` and link it to `foo`
    var bar = Object.create( foo );
    bar.fooprops= "We checking prototypes";
    console.log(bar.__proto__); // "foo"
    console.log(bar.fooprops); // "We checking prototypes"
    console.log(bar.check); // 10 is delegated to `foo`
    
    0 讨论(0)
  • 2020-11-21 06:48

    I know, I am late but let me try to simplify it.

    Let us say there is a function

        function Foo(message){
    
             this.message = message ; 
         };
    
         console.log(Foo.prototype);
    

    Foo function will have a prototype object linked. So,Whenever we create a function in JavaScript, it always has a prototype object linked to it.

    Now let us go ahead and create two objects using the function Foo.

        var a = new Foo("a");
        var b = new Foo("b");
        console.log(a.message);
        console.log(b.message);
    
    1. Now we have two objects, object a and object b. Both are created using constructor Foo. Keep in mind constructor is just a word here.
    2. Object a and b both have a copy of message property.
    3. These two objects a and b are linked to prototype object of constructor Foo.
    4. On objects a and b, we can access Foo prototype using __proto__ property in all browsers and in IE we can use Object.getPrototypeOf(a) or Object.getPrototypeOf(b)

    Now, Foo.prototype, a.__proto__, and b.__proto__ all denotes same object.

        b.__proto__ === Object.getPrototypeOf(a);
        a.__proto__ ===  Foo.prototype;
        a.constructor.prototype  === a.__proto__;
    

    all of above would return true.

    As we know, in JavaScript properties can be added dynamically. We can add property to object

        Foo.prototype.Greet = function(){
    
             console.log(this.message);
        }
        a.Greet();//a
        b.Greet();//b
        a.constructor.prototype.Greet();//undefined 
    

    As you see we added Greet() method in Foo.prototype but it is accessible in a and b or any other object which is constructed using Foo.

    While executing a.Greet(), JavaScript will first search Greet in object a on property list. On not finding , it will go up in __proto__ chain of a. Since a.__proto__ and Foo.prototype is same object, JavaScript will find Greet() method and execute it.

    I hope, now prototype and __proto__ is simplified a bit.

    0 讨论(0)
  • 2020-11-21 06:48

    !!!THIS IS THE BEST EXPLANATION IN THE WORLD!!!!!

    var q = {}
    var prototype = {prop: 11}
    
    q.prop // undefined
    q.__proto__ = prototype
    q.prop // 11
    

    in function constructors javascript engine call this q.__proto__ = prototype automatically when we write new Class, and in to the __proto__ prop set Class.prototype

    function Class(){}
    Class.prototype = {prop: 999} // set prototype as we need, before call new
    
    var q = new Class() // q.__proto__ = Class.prototype
    q.prop // 999
    

    Enjoy %)

    0 讨论(0)
  • 2020-11-21 06:49

    prototype

    prototype is a property of a Function. It is the blueprint for creating objects by using that (constructor) function with new keyword.

    __proto__

    __proto__ is used in the lookup chain to resolve methods, properties. when an object is created (using constructor function with new keyword), __proto__ is set to (Constructor) Function.prototype

    function Robot(name) {
        this.name = name;
    }
    var robot = new Robot();
    
    // the following are true   
    robot.__proto__ == Robot.prototype
    robot.__proto__.__proto__ == Object.prototype
    

    Here is my (imaginary) explanation to clear the confusion:

    Imagine there is an imaginary class (blueprint/coockie cutter) associated with function. That imaginary class is used to instantiate objects. prototype is the extention mechanism (extention method in C#, or Swift Extension) to add things to that imaginary class.

    function Robot(name) {
        this.name = name;
    }
    

    The above can be imagined as:

    // imaginary class
    class Robot extends Object{
    
        static prototype = Robot.class  
        // Robot.prototype is the way to add things to Robot class
        // since Robot extends Object, therefore Robot.prototype.__proto__ == Object.prototype
    
        var __proto__;
    
        var name = "";
    
        // constructor
        function Robot(name) {
    
            this.__proto__ = prototype;
            prototype = undefined;
    
            this.name = name;
        }
    
    } 
    

    So,

    var robot = new Robot();
    
    robot.__proto__ == Robot.prototype
    robot.prototype == undefined
    robot.__proto__.__proto__ == Object.prototype
    

    Now adding method to the prototype of Robot:

    Robot.prototype.move(x, y) = function(x, y){ Robot.position.x = x; Robot.position.y = y};
    // Robot.prototype.move(x, y) ===(imagining)===> Robot.class.move(x, y)
    

    The above can be imagined as extension of Robot class:

    // Swift way of extention
    extension Robot{
        function move(x, y){    
            Robot.position.x = x; Robot.position.y = y
        }
    }
    

    Which in turn,

    // imaginary class
    class Robot{
    
        static prototype = Robot.class // Robot.prototype way to extend Robot class
        var __proto__;
    
        var name = "";
    
        // constructor
        function Robot(name) {
    
            this.__proto__ = prototype;
            prototype = undefined;
    
            this.name = name;
        }
    
        // added by prototype (as like C# extension method)
        function move(x, y){ 
            Robot.position.x = x; Robot.position.y = y
        };
    }
    
    0 讨论(0)
  • 2020-11-21 06:49

    What about using __proto__ for static methods?

    function Foo(name){
      this.name = name
      Foo.__proto__.collection.push(this)
      Foo.__proto__.count++
    
    }
    
    Foo.__proto__.count=0
    Foo.__proto__.collection=[]
    
    var bar = new Foo('bar')
    var baz = new Foo('baz')
    
    Foo.count;//2
    Foo.collection // [{...}, {...}]
    bar.count // undefined
    
    0 讨论(0)
提交回复
热议问题