Search code examples
javascriptprototypal-inheritance

Why is obj.constructor.prototype not always equal to obj.__proto__?


function Product(name, price) {
  this.name = name;
  this.price = price;
}

const p1 = new Product('Pen', 20);
const p2 = Object.create(p1);

console.log(p1.constructor.prototype === p1.__proto__);  // true
console.log(p2.constructor.prototype === p2.__proto__);  // false

My understanding was these two are always equal (as in the first console.log statement).

But, while doing some tweaks I found this surprising result (second console.log statement).

Can someone please clear up my understanding about the relationship between prototype and __proto__. Thanks in advance!


Solution

  • This only works for instances created using new from constructors that follow the standard prototype pattern. These objects will inherit from the constructors .prototype object, which has a .constructor property pointing back to the constructor. This means when accessing the inherited .constructor, we can find the prototype object that we're inheriting on it.

    However, it doesn't work for arbitrary objects that have their own .constructor property (e.g. {constructor: null}) or for objects that don't inherit directly from a constructor's prototype object, such as your p2.

    To clarify what's happening in your code without using new:

    const Product = Object.create(Function.prototype);
    Product.prototype = Object.create(Object.prototype);
    Product.prototype.constructor = Product;
    
    const p1 = Object.create(Product.prototype);
    p1.name = "Pen";
    p1.price = 20;
    console.assert(Product.prototype == Object.getPrototypeOf(p1));
    console.assert(!p1.hasOwnProperty("constructor") && p1.constructor == Product);
    console.assert(p1.constructor.prototype == Product.prototype);
    console.assert(p1.constructor.prototype == Object.getPrototypeOf(p1));
    
    const p2 = Object.create(p1);
    console.assert(p1 == Object.getPrototypeOf(p2));
    console.assert(!p2.hasOwnProperty("constructor") && p2.constructor == p1.constructor);