Reputation: 1214
I'm reading this book. Check section "15.6.4.2 Pitfall: A method that uses super can’t be moved"
It states the following
You can’t move a method that uses super: Such a method has the internal slot [[HomeObject]] that ties it to the object it was created in. If you move it via an assignment, it will continue to refer to the superproperties of the original object.
So, I tried to call it with a different object, also assign instance method to a different object but it seems not to work. It refers to new object's properties. Probably, I didn't get correctly what the author means. So, could anyone, please, provide an example?
Hers is a small demo and the code below
class A {
get a() {
return 1;
}
sayHi() {
console.log(this.a)
}
}
class B extends A {
sayHi() {
super.sayHi();
};
}
var obj = {
a: 4
};
let b = new B();
b.sayHi();
// logs 1
b.sayHi.call(obj);
// logs 4
obj.sayHi = b.sayHi;
obj.sayHi();
// logs 4
Upvotes: 4
Views: 360
Reputation: 25741
Your code is OK, because this
works when you move a method, but super
doesn’t (and your code only really tests this
). The following code tests super
:
class Bird {
getName() {
return 'Bird';
}
}
class Mammal {
getName() {
return 'Mammal';
}
}
class Human extends Mammal {
getName() {
return super.getName();
}
}
class Duck extends Bird {
}
// Moving method .getName() from Human.prototype to Duck.prototype
Duck.prototype.getName = Human.prototype.getName;
console.log(new Duck().getName()); // 'Mammal' (not 'Bird')
To understand the result, you need to understand how super
works – it uses the internal property [[HomeObject]]
that is stored in the method itself, it does not rely on this
. That is, Human.prototype.getName()
internally works as follows:
Human.prototype.getName = Object.assign(
function me() {
return me.__HomeObject__.__proto__.getName();
},
{ __HomeObject__: Human.prototype }
);
More details are explained in the book:
Upvotes: 7
Reputation: 664385
OP is saying that super.sayHi()
will always call A.prototype.sayHi
, regardless on what object you call the method. One might have expected
const sayHi = new B().sayHi; // or B.prototype.sayHi
const prototype = {
sayHi() {
console.log("not the a property");
}
};
const myObject = Object.assign(Object.create(prototype), {
a: "the a property"
});
myObject.sayHi = sayHi;
myObject.sayHi();
// or just sayHi.call(myObject);
to log not the a
property - by calling prototype.sayHi
through the prototype chain of myObject
. But that is not what happens, it logs the a
property as normal.
Upvotes: 1