-1

The code below is what I test in browser.

function A(){}
a = new A()

a.__proto__ === a //false
a.__proto__.constructor === a.constructor //true

It's confusing for me why a.__proto__ and a share the same .constructor

2
  • 1
    "It's really confusing why the constructor property is implemented this way." Why? Commented Apr 30, 2019 at 7:09
  • 3
    You are overestimating how much your question makes sense, in absence of an explicit question. There is nothing confusing there for me, it is quite obvious from the way prototypal inheritance works in JS. Please clarify, or the question is likely to be closed as vague. Commented Apr 30, 2019 at 7:10

2 Answers 2

4

a.__proto__ === a is false because a is not its own prototype. They're separate objects

a.__proto__.constructor === a.constructor is true because the a object inherits the constructor property from its prototype. So you can access the property on a (indirectly) or on its prototype.

When you do a = new A(), here's a rough idea of what you have in memory (handwaving away some details), which may help:

     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     |                                                             |
     |  +−−−−−−−−−−−−−−−+                                          |
A−−−−+−>|  (function)   |                                          |
        +−−−−−−−−−−−−−−−+                                          |
        | name: "A"     |                        +−−−−−−−−−−−−−−−+ |
        | prototype     |−−−−−−−−−−−−−−−−−−−−−+−>|   (object)    | |
        | [[Prototype]] |−>Function.prototype |  +−−−−−−−−−−−−−−−+ |
        | [[Code]]      |                     |  | constructor   |−+                
        +−−−−−−−−−−−−−−−+                     |  | [[Prototype]] |−>Object.prototype
                                              |  +−−−−−−−−−−−−−−−+
   +−−−−−−−−−−−−−−−+                          |  
a−>|   (object)    |                          |
   +−−−−−−−−−−−−−−−+                          |
   | [[Prototype]] |−−−−−−−−−−−−−−−−−−−−−−−−−−+
   +−−−−−−−−−−−−−−−+           

([[Prototype]] is a link to the object's prototype, the value returned by the deprecated __proto__ and by the modern Object.getPrototypeOf(). Also: Function.prototype's prototype is Object.prototype, not shown above.)

A is a constructor function. It has a property, prototype, which points to the object that will be used as the prototype of objects created via new A. a is an object created via new A, so its prototype ([[Prototype]]) is that same object. The A.prototype object has a property, constructor, that refers back to the constructor function it's associated with (in the simple, default case).

It becomes a bit more useful when you have two instances, a1 and a2. Let's modify the code a bit:

// Part 1
function A(foo) {
    this.foo = foo;
}
A.prototype.method = function() {
    console.log(this.foo);
};

// Part 2
const a1 = new A("one");
const a2 = new A("two");

a1.method(); // "one"
a2.method(); // "two"

After Part 1 above runs, we have something like this (again, leaving out some details, and I've used Fp and Op instead of Function.prototype and Object.prototype to save space):

     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     |                                           |
     |  +−−−−−−−−−−−−−−−+                        |
A−−−−+−>|  (function)   |                        |
        +−−−−−−−−−−−−−−−+                        |
        | name: "A"     |      +−−−−−−−−−−−−−−−+ |
        | prototype     |−−−−−>|   (object)    | |
        | [[Prototype]] |−>Fp  +−−−−−−−−−−−−−−−+ |
        | [[Code]]      |      | constructor   |−+    +−−−−−−−−−−−−−−−−+
        +−−−−−−−−−−−−−−−+      | method        |−−−−−>|   (function)   |
                               | [[Prototype]] |−>Op  +−−−−−−−−−−−−−−−−+
                               +−−−−−−−−−−−−−−−+      | name: "method" |
                                                      | [[Prototype]]  |−>Fp
                                                      | [[Code]]       |
                                                      +−−−−−−−−−−−−−−−−+

After the const a1 = new A("one"); line, we have:

     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     |                                              |
     |  +−−−−−−−−−−−−−−−+                           |
A−−−−+−>|  (function)   |                           |
        +−−−−−−−−−−−−−−−+                           |
        | name: "A"     |         +−−−−−−−−−−−−−−−+ |
        | prototype     |−−−−−−+−>|   (object)    | |
        | [[Prototype]] |−>Fp  |  +−−−−−−−−−−−−−−−+ |
        | [[Code]]      |      |  | constructor   |−+    +−−−−−−−−−−−−−−−−+
        +−−−−−−−−−−−−−−−+      |  | method        |−−−−−>|   (function)   |
                               |  | [[Prototype]] |−>Op  +−−−−−−−−−−−−−−−−+
                               |  +−−−−−−−−−−−−−−−+      | name: "method" |
                               |                         | [[Prototype]]  |−>Fp
                               |                         | [[Code]]       |
                               |                         +−−−−−−−−−−−−−−−−+
     +−−−−−−−−−−−−−−−+         |
a1−−>|   (object)    |         |
     +−−−−−−−−−−−−−−−+         |
     | foo: "one"    |         |
     | [[Prototype]] |−−−−−−−−−+
     +−−−−−−−−−−−−−−−+

After the const a2 = new A("two"); line, we have:

     +−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−+
     |                                              |
     |  +−−−−−−−−−−−−−−−+                           |
A−−−−+−>|  (function)   |                           |
        +−−−−−−−−−−−−−−−+                           |
        | name: "A"     |         +−−−−−−−−−−−−−−−+ |
        | prototype     |−−−−−−+−>|   (object)    | |
        | [[Prototype]] |−>Fp  |  +−−−−−−−−−−−−−−−+ |
        | [[Code]]      |      |  | constructor   |−+    +−−−−−−−−−−−−−−−−+
        +−−−−−−−−−−−−−−−+      |  | method        |−−−−−>|   (function)   |
                               |  | [[Prototype]] |−>Op  +−−−−−−−−−−−−−−−−+
                               |  +−−−−−−−−−−−−−−−+      | name: "method" |
                               |                         | [[Prototype]]  |−>Fp
                               |                         | [[Code]]       |
                               |                         +−−−−−−−−−−−−−−−−+
     +−−−−−−−−−−−−−−−+         |
a1−−>|   (object)    |         |
     +−−−−−−−−−−−−−−−+         |
     | foo: "one"    |         |
     | [[Prototype]] |−−−−−−−−−+
     +−−−−−−−−−−−−−−−+         |
                               |
     +−−−−−−−−−−−−−−−+         |
a2−−>|    (object)   |         |
     +−−−−−−−−−−−−−−−+         |
     | foo: "two"    |         |
     | [[Prototype]] |−−−−−−−−−+
     +−−−−−−−−−−−−−−−+

That shows how the prototype is useful for shared features. a1 and a2 don't need to have their own copies of method, they just inherit it from their prototype.


Side note: __proto__ is deprecated. Use Object.getPrototypeOf(a) to get the prototype of a, rather than a.__proto__.

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for the detailed explanation. It's quite helpful. a instanceof A //true a.constructor === A //true Object.getPrototypeOf(a) instanceof Object //true Object.getPrototypeOf(a).constructor === Object //false I was expecting that if some_object is an instance of another_object, then another_object should be the constructor of some_object. It appears that it's not the case.
@Sean - obj instanceof Ctor looks to see if Ctor.prototype is anywhere in obj's inheritance chain. So a instanceof A is true because a's immediate prototype is A.prototype. a instanceof Object is also true, because the prototype of a's prototype is Object.prototype. (Object.getPrototypeOf(Object.getPrototypeOf(a)) === Object.prototype.)
@Sean - I've updated the answer to show Object.prototype and Function.prototype in the places they go, for more clarity. (Also, a couple of the lines in the final two diagrams were misplaced.) Happy coding!
2

A.prototype.constructor == A for any function A; a.__proto__ == A.prototype for any object a constructed by new A; a.constructor doesn't exist, so it is looked up up the prototype chain just like any other attribute, and is found at a.__proto__.constructor.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.