JavaScript constructor objects have a special attribute named “prototype”. It allows functions and attributes to become inheritable.

For example, dad who is inherently a Person, could be represented like this:

  // The person constructor
  function Person ( firstNames, lastName ) {
    this.firstNames = firstNames;
    this.lastName = lastName;
  };
  
  /*
   * Attribute that will be available to 
   * all instances of Person
   */
  Person.prototype.fullName = function () {
    return this.firstNames + ' ' + this.lastName;
  };
  
  var dad = new Person( 'John', 'Smith' );
  
  dad.fullName(); // => "John Smith"
  

The prototype attribute can also be used for object inheritance. Now we create mom who not only is a instance of Person, but a instance of the Smith aswell.

  
  // The smith constructor
  function Smith ( name ) {
    this.name = name;
  };
  
  Smith.prototype = new Person( '', 'Smith' );
  
  var mom = new Smith('Joana'); 
  
  mom.fullName(); // => 'Joana Smith';
  

The Prototype library has made extensive use of this special attribute, for example, they have a Array.prototype.each that works something like this:

  
  /*
   * iterates through an array
   * and calls the "block" 
   * for every item in the array.
   */
  Array.prototype.each = function ( block ) {
  
    // "this" is the array 
    for( var a = 0; a < this.length; a++ )
      block.call( this, a, this[a] );
    return this;
  };
  

Because Javascript has first-class functions, you can pass a function as a argument to another function. We can now pass a function to the Array’s “each” method to scan through the array without coding yet another for loop…

  
  var list = [ 'zero', 'one', 'two', 'three' ]
  var string = '';
  
  // we could use a for-loop
  for( var a = 0, l = list.length; a < l; a++ ) {
    string += list[a] + ' ';
  };
  
  // or we could use the ".each" function.
  list.each(function(index,value){
    string += value + ' ';
  })
  

The advantage of using prototype stored functions like above is that it scales easier than implementing loads of for-loops and it follows the DRY standard.

Introducing Object.prototype

Most objects in javascript are inherited from the Object constructor. And we could easily add methods such as each to objects aswell.

However, there is a small problem. If we said

  
  Object.prototype.each = function ( block ) {
    for( var a in this )
      void block.call( this, a, this[a] );
    return this;
  }
  

The each on a block won’t work as expected. Since each would also be passed as a argument to the block during the “for-in” loop.

  
  var obj = { one: 1, two: 2, three: 3 };
  var string = "";
  
  /*
   * The 'each' attribute will be included
   * in the loop for the each function,
   * aswell as for any normal for-in loop.
   */
  
  obj.each(function(attrName,attrValue){
    string += name + ', ';
  })
  
  alert( string ) // => "one, two, three, each, "
  
  string = "";
  
  // normal for-in loop
  for( var attr in obj ) {
    string += name + ', ';
  }
  
  alert( string ) // => "one, two, three, each, "
  

This problem has led to many developers spurning the use of Object.prototype. They encourage others to avoid using it.

So, let’s be rebelious… :)

There is a function called hasOwnProperty

Basically, it checks the attribute of an object, returns true if the attribute belongs to the object and false if it belongs to its constructor.

 
 Object.prototype.each = function () {
   // code for each function
 }
  
 var obj = { one: 1, two: 2, three: 3 };
 
 alert( obj.hasOwnProperty('one') ) // => true
 alert( obj.hasOwnProperty('each') ) // => false
  

The hasOwnProperty method allows us to distinguish between attributes we would want to scan and inherited attributes we won’t.

So here’s the better Object.prototype.each method:

  
  Object.prototype.each = function (block) {
    for( var attr in this ) {
      if( this.hasOwnProperty( attr ) )
        void block.call( this, a, this[a] )
    };
    return this;
  }
  

Some might still not like the idea of using Object.prototype, but it’s worth spending some time on.