A Formal Method Definition
Prior to ECMAScript 6, the concept of a “method” wasn’t formally defined. Methods were just object properties that contained functions instead of data. ECMAScript 6 formally defines a method as a function that has an internal [[HomeObject]]
property containing the object to which the method belongs. Consider the following:
let person = {
// method
getGreeting() {
return "Hello";
}
};
// not a method
function shareGreeting() {
return "Hi!";
}
This example defines person
with a single method called getGreeting()
. The [[HomeObject]]
for getGreeting()
is person
by virtue of assigning the function directly to an object. The shareGreeting()
function, on the other hand, has no [[HomeObject]]
specified because it wasn’t assigned to an object when it was created. In most cases, this difference isn’t important, but it becomes very important when using super
references.
Any reference to super
uses the [[HomeObject]]
to determine what to do. The first step is to call Object.getPrototypeOf()
on the [[HomeObject]]
to retrieve a reference to the prototype. Then, the prototype is searched for a function with the same name. Last, the this
binding is set and the method is called. Here’s an example:
let person = {
getGreeting() {
return "Hello";
}
};
// prototype is person
let friend = {
getGreeting() {
return super.getGreeting() + ", hi!";
}
};
Object.setPrototypeOf(friend, person);
console.log(friend.getGreeting()); // "Hello, hi!"
Calling friend.getGreeting()
returns a string, which combines the value from person.getGreeting()
with ", hi!"
. The [[HomeObject]]
of friend.getGreeting()
is friend
, and the prototype of friend
is person
, so super.getGreeting()
is equivalent to person.getGreeting.call(this)
.