Search code examples
javascriptinheritanceecmascript-6propertiesv8

Why __proto__ reference name look like wrong for inherited object?


class Human{
    talk(){
        return 'talking';
    }
}
class SuperHuman extends Human{
    constructor(){
        super();
        this.age = 12;
    }
    fly(){
        return 'flying';
    }
}
let me = new Human();
let you = new SuperHuman();
you.gender = 'male';
console.log(you);
let she = Object.create(you);
console.log(she);

when study prototypal inheritance the she(object) proto looks like this.

shows out put

but my expectation is it should look like this...

but my expected output

Why it shows in this way?


Solution

  • Devtools is just telling you that the prototype of she is a SuperHuman (specifically, you), not that the prototype is the function SuperHuman.

    The prototype chain of she is:

    she −> you −> SuperHuman.prototype −> Human.prototype −> Object.prototype
    
    • she's prototype is you because you created it with Object.create(you).
    • you's prototype is SuperHuman.prototype because you created it with new SuperHuman.
    • SuperHuman.prototype's prototype is Human.prototype because you created the SuperHuman function via class SuperHuman extends Human which sets up two chains of inheritance (one for the prototype objects and the other for the functions themselves).
    • Human.prototype's prototype is Object.prototype because that's what class does when there's no extends.

    As a complete aside, it's unfortunate that some devtools implementations (such as the one in Chromium-based browsers) use __proto__ where what they mean is [[Prototype]]. For one thing, it encourages using __proto__, which one shouldn't (not all objects have it and it can be shadowed; always use Object.getPrototypeOf or Object.setPrototypeOf). Separately, it's misleading: Chromium's devtools will happily show you __proto__ for an object that doesn't have the __proto__ accessor property at all because it doesn't inherit from Object.prototype (which is where the accessor comes from):

    // An object with no prototype
    const p = Object.create(null);
    
    // An object using that as its prototype
    const c = Object.create(p);
    
    // An object inheriting from Object.prototype has the `__proto__` accessor property:
    console.log("__proto__" in {}); // true
    
    // `c` does not have the `__proto__` accessor property:
    console.log("__proto__" in c); // false
    
    // And yet, Chromium's devtools show you one if you expand it in the console
    console.log(c);
    Look in the real browser console.