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:

  1. let person = {
  2. // method
  3. getGreeting() {
  4. return "Hello";
  5. }
  6. };
  7. // not a method
  8. function shareGreeting() {
  9. return "Hi!";
  10. }

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:

  1. let person = {
  2. getGreeting() {
  3. return "Hello";
  4. }
  5. };
  6. // prototype is person
  7. let friend = {
  8. getGreeting() {
  9. return super.getGreeting() + ", hi!";
  10. }
  11. };
  12. Object.setPrototypeOf(friend, person);
  13. 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).