glenatron
glenatron

Reputation: 11372

Binding a function to a prototype in a JavaScript inheritance hierarchy

What I want to do is retrofit a serialisation method to an existing JavaScript type, which is a member of an inheritance tree. It is very nearly working, but my function is operating on the parent type rather than the type I am trying to associate it with. So to take a very basic example:

function Animal( species, population ) 
{
   this.species = species;
   this.population = population;
}

Animal.prototype.getDetail = function() 
{
   return "Species: "+this.species+" Population: "+this.population;
}

function Mammal( species, population, bodyTemperature )
{
    Animal.apply(this, [species, population]);
    this.bodyTemperature = bodyTemperature;
}
Mammal.prototype= new Animal();
Mammal.constructor = Mammal;

var Serialise= {
    init: function() {
        Mammal.prototype.serialise = this.serialiseMammal.bind(Mammal.prototype);
    },

    serialiseMammal: function() {
       return {
            species: this.species,
            population: this.population,
            bodyTemperature: this.bodyTemperature
       };
    }   
}

Serialise.init();

var bob = new Mammal("Human", 7000000000, 36.6);

console.log( bob.serialise() );

What is happening is that the serialise function is running in the context of the Animal type which is correct because that is the prototype of Mammal, but if I try to bind it directly to the Mammal, nothing happens at all. Once again, I find myself out of my depth in JavaScript's scope.

The reason I am doing this is to keep all my serialisation/deserialisation in one place, so that it's there if I need it, but I don't always have to have it included- I guess in another language it might be behaving slightly like a mixin.

What do I need to do to ensure that the any call of serialise() on an instance of the Mammal type will correctly apply the Serialise.serialiseMammal()function in the context of the current instance? Is there a way of doing this without binding the functions to individual instances when they are created?

I'm also trying to improve my own expertise with the language and doing things in more of a JavaScript way, so if the whole approach is totally wack or against the grain of the language, that would be good to know.

Upvotes: 0

Views: 63

Answers (1)

deitch
deitch

Reputation: 14581

I do not fully understand why you want to decorate it this way, as opposed to just putting the specialized serialiseMammal directly on the Mammal.prototype, as below:

Mammal.prototype.s2 = function() {
    return {
        species: this.species,
        population: this.population,
        bodyTemperature: this.bodyTemperature
    };
};

I called this s2 so as not to conflict. This is the identical code from serialiseMammal. However, if you prefer the decorator-style pattern you have used, then you just need to do:

var Serialise= {
    init: function() {
        Mammal.prototype.serialise = this.serialiseMammal;
    },

    serialiseMammal: function() {
        return {
            species: this.species,
            population: this.population,
            bodyTemperature: this.bodyTemperature
       };
    }   
}

Within the context of init, then this refers to Serialise, so this.serialiseMammal is the function you have. But it is just a function, nothing more. When you next call bob.serialise(), the function is called in the context of the moment. This, this inside of bob.serialise(), which is the code from serialiseMammal, is set to bob.

Here is a fiddle with it. http://jsfiddle.net/6un6qho1/1/

Upvotes: 1

Related Questions