You’re mostly right, except for “Point is the prototype of myPoint” and “The __proto__
property of myPoint is pointing to its prototype, which is Point.” These are not correct. Point is just the constructor of myPoint, and the prototype of myPoint is actually Point.prototype
.
The biggest thing to be careful of here is naming. There are “prototypes” and there are prototype
properties. These are not the same thing. The prototype of any object is what its __proto__
property points to - something referred to as “[[Prototype]]” in the spec. The prototype is what an object uses to access shared properties when access is made on a property that it doesn’t have defined on its own instance.
var shared = { num: 1 };
var instance = { str: "a" };
console.log(instance.str); // "a"
console.log(instance.num); // undefined
Object.setPrototypeOf(instance, shared);
console.log(instance.str); // "a"
console.log(instance.num); // 1 <- coming from its prototype
When you create a constructor function like Point
, it is created with a prototype
property. This is not the prototype of the Point
function object. It actually has it’s own prototype which you can access through Point.__proto__
, This awkwardly named prototype
property actually refers to the object which gets set as the prototype (i.e. __proto__
value) for the instances created from Point
when used as a constructor with the new
keyword. The prototype
property would be better named as prototypeForInstancesThisConstructorCreates
.
function Point(x, y) {
this.x = x;
this.y = y;
}
var myPoint = new Point();
console.log(myPoint.__proto__ === Point.prototype); // true
Notice here that myPoint
's prototype is being referenced by a __proto__
property (not a prototype
property) and the value in the prototype
property of Point
is not Point
's prototype. Seems a little backwards, doesn’t it?
Basically what happens is, when Point
is used as a constructor, internal code in the JavaScript runtime performs this:
// pseduocode
if (is_called_with_new(current_function)) {
this = allocate_new_object_instance()
Object.setPrototypeOf(this, current_function.prototype)
set_default_return_value_of(current_function, this)
}
Object.setPrototypeOf
is what sets up the __proto__
link. (Note: generally the use of __proto__
is discouraged in favor of Object.setPrototypeOf
and Object.getPrototypeOf
, though __proto__
is what you see when debugging objects so its good to know what it means.) So what you get from new Point
is a new JavaScript object that is mostly like a new {}
object, but has a prototype refering to the prototype
property of the function that created it. That and the function gets run with this
being a reference to that object which in the case of Point
here, also assigns some x
and y
properties to the object.