May 25, 2015

Notes on object-oriented JavaScript for o-o developers (part 4)

This post continues with more notes on distinctive features of object-oriented JavaScript as described in the book The Principles of Object-Oriented JavaScript.

The post is a follow-up to the earlier  Part 3.

**  Prototype chaining provides inheritance.

Almost all objects refer to a prototype, from which methods and properties are inherited that are defined in the prototype rather than in the object itself.

But an object's prototype is itself an object with its own prototype (usually). This chain normally goes all the way back to Object.prototype.

The object inherits the methods and properties of each of these prototypes. When a method is called, the JavaScript interpreter walks the chain to search for it. The first occurrence that is found is the one that is used. (That occurrence shadows any others that may be defined farther along in the chain.)

This means that pretty much every object inherits generally useful methods such as valueOf() and toString() from Object.prototype.

Here's a simple example of inheritance via prototypes.

  function Pet(name) {
    this.name = name;
  }
  Pet.prototype.getName = function () { return this.name; };


  my_pet = new Pet('My Pet');

  function Dog(name) {
    this.name = name;
  }
  Dog.prototype = my_pet;

  Dog.prototype.constructor = Dog;

  my_dog = new Dog('Foghat');


  console.log(my_dog.getName());  // Displays 'Foghat'


An instance of Pet is created, then it is assigned as the prototype for the Dog constructor. So the getName() method is indirectly inherited by the instance of Dog.

(The constructor property of Dog.prototype has to be restored to refer to Dog. Otherwise, it would refer to Pet, which is not correct.)

A slightly more concise and cleaner version of this example is

  function Pet(name) {
    this.name = name;
  }
  Pet.prototype.getName = function () { return this.name; };


  function Dog(name) {
    this.name = name;
  }
  Dog.prototype =
new Pet();
  Dog.prototype.constructor = Dog;

  my_dog = new Dog('Foghat');


  console.log(my_dog.getName());  // Displays 'Foghat'


We still create an instance of Pet,but it is anonymously assigned directly as the prototype for Dog.

The argument to the Pet constructor can be omitted since it isn't used in this particular use case.

This example chains from one constructor to another so it is known as constructor inheritance. However, the prototype chain may also consist of objects that are not constructors.

Caveat: prototype chaining works well for inheriting methods, but not for inheriting data properties that are intended to be instance data, that is, data with values that are unique to each object. That's because prototype objects are shared, therefore, their data properties are also shared among all objects that have the same prototype. These are like static or class variables in other languages.

(Continued at the final Part 5.)

No comments:

Post a Comment