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
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
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__.
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.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.)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!