Search code examples
javascriptobjectprototype

Why assignment to the doesn't the object __proto__ doesn't work?


Case 1 :- Initially in object literal I assign __proto__ to null and then I'm trying to reassign it to animal, which is not working.

'use strict'
let animal = {
    eats: true,
    walk(){
        console.log('Animal Walk');
    }
}

let rabbit = {
    jumps: true,
    __proto__: null
}

rabbit.__proto__ = animal
console.log(Object.getPrototypeOf(rabbit))
rabbit.walk()

Case 2:- Now i assign __proto__ in object literal as animal and later i try to reassign it to null, it changes __proto__ to null in this case.

'use strict'
let animal = {
    eats: true,
    walk(){
        console.log('Animal Walk');
    }
}

let rabbit = {
    jumps: true,
    __proto__: animal
}

rabbit.__proto__ = null
console.log(Object.getPrototypeOf(rabbit))
rabbit.walk()

Case 3:- When i use Object.setPrototypeOf() it works fine

'use strict'
let animal = {
    eats: true,
    walk(){
        console.log('Animal Walk');
    }
}

let rabbit = {
    jumps: true,
    __proto__: null
}

Object.setPrototypeOf(rabbit, animal)
console.log(Object.getPrototypeOf(rabbit))
rabbit.walk()

Why isn't the assignment working in the first case?


Solution

  • Okay, this is a bit tricky. :-) There are two different __proto__ meanings being used by your code:

    1. The __proto__ token in object literals that can specify the object's initial prototype, and
    2. The __proto__ accessor property (when you get/set it after object creation)

    The reason rabbit.__proto__ = animal doesn't change rabbit's prototype is that __proto__ is an accessor property defined by Object.prototype. Since you create rabbit without any prototype (by using __proto__: null in the object literal), rabbit doesn't inherit that accessor, so rabbit.__proto__ = animal just creates a property on rabbit called __proto__ rather than changing its prototype.

    Both of those meanings for __proto__ are legacy web-only (Annex B) compatibility things. Use Object.create (to create an object with a specific prototype), Object.getPrototypeOf, and (if you can't avoid changing an object's prototype) Object.setPrototypeOf. JavaScript engines outside of browsers aren't required to implement Annex B features like __proto__ (though in my experience, engines don't disable most of them outside browsers).