Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does an instantiated object still have a property of the prototype even after the prototype is reassigned to an empty object? [duplicate]

Tags:

javascript

function Rabbit() {}
Rabbit.prototype = {
  eats: true
};

let rabbit = new Rabbit();

Rabbit.prototype = {};

alert( rabbit.eats ); // ?
Why rabbit.eat shows true when we set its reference i.e constructor Function prototype Rabbit to empty?

Of what i know that when the compiler reads the statement (rabbit.eat) it first checks in the object whether the property exist or not then it looks in the rabbit.__proto__ i.e the Rabbit.prototype for the property. but here we assign Rabbit.prototype = {} so why the object rabbit still have eat property??

like image 349
Amandeep Saini Avatar asked Jan 19 '26 14:01

Amandeep Saini


1 Answers

The prototype of the instantiated Rabbit, the rabbit, is still the original Rabbit.prototype object, which has eats: true. Reassigning the prototype does not mean that the interpreter goes through every instantiated object and changes the prototype.

If you wanted to change the prototype of an existing object, you can use setPrototypeOf, like this:

function Rabbit() {}
Rabbit.prototype = {
  eats: true
};
let rabbit = new Rabbit();
Rabbit.prototype = {};
Object.setPrototypeOf(rabbit, Rabbit.prototype);
alert(rabbit.eats); // ?

But:

Warning: Changing the [[Prototype]] of an object is, by the nature of how modern JavaScript engines optimize property accesses, a very slow operation, in every browser and JavaScript engine. The effects on performance of altering inheritance are subtle and far-flung, and are not limited to simply the time spent in Object.setPrototypeOf(...) statement, but may extend to any code that has access to any object whose [[Prototype]] has been altered. If you care about performance you should avoid setting the [[Prototype]] of an object. Instead, create a new object with the desired [[Prototype]] using Object.create().

Alternatively, instead of reassigning the prototype, you could mutate the prototype into an empty object:

function Rabbit() {}
Rabbit.prototype = {
  eats: true
};
let rabbit = new Rabbit();

// `for..in` will iterate over all properties, including inherited ones
// if you don't want that, iterate over Object.keys instead
for (const key in Rabbit.prototype) {
  delete Rabbit.prototype[key];
}

console.log(rabbit.eats);

Other mutations to rabbit's original prototype will also change what you can access on rabbit, as long as you aren't reassigning the class's prototype (which creates a separate unlinked object):

function Rabbit() {}
Rabbit.prototype = {
  eats: true
};
let rabbit = new Rabbit();
// mutation, not reassignment
Rabbit.prototype.eats = 'foo';

console.log(rabbit.eats); // ?
like image 158
CertainPerformance Avatar answered Jan 21 '26 04:01

CertainPerformance



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!