1

(Open to edits for a better question title - it was difficult to phrase what I am looking for)

Hi,

I have been working with prototypes, but have recently come across the need for a namespace within a prototype to group related functions. The code, in its most simplistic form, looks like this:

// Base grid functions.
Grid.prototype = {

    init: function init() {
        document.getElementById("output").innerHTML += "<br>" + this.id;

        this.Rows.init();

        this.Test.init();

        document.getElementById("output").innerHTML += "<br><br>";
    },

    Test: {
        init: function init() {
            document.getElementById("output").innerHTML += "<br>" + this.id;
        }
    }

};

// Additional row-related and row utility functions.
Grid.prototype.Rows = {

    init: function init() {
        document.getElementById("output").innerHTML += "<br>" + this.id;
    }
};

In my Rows "namespace", I wanted to maintain the context of this so devs can call on functions like gridInstance.Rows.get(), for example, without having to pass the context in each time (via call or apply).

To do this I used LoDash's _.bind function to set the context of, what I thought would be, each new Grid instance to each of its row-related functions.

Note the Test "namespace" was purely to see if, when nested inside the Grid prototype, it would have a differing result.

var Grid = function Grid(id) {
    var t = this;

    // Assign an id to the control.

    if (!id) {
        // Assign a custom id if the control does not have one.
        id = "grid-" + new Date().getTime();
    }

    t.id = id;

    _.each(t.Rows, function (rowFn, key) {
        t.Rows[key] = _.bind(rowFn, t);
    });

    _.each(t.Test, function (rowFn, key) {
        t.Test[key] = _.bind(rowFn, t);
    });

    t.init();
};

There is a fiddle here, showing the output:

x x x

y x x

z x x

My question is, why does the the Rows prototype not get instantiated as new (like the Grid.prototype each time you call on new Grid() and how can I work around this?

Additional Thoughts

My thinking was that the Grid.prototype acts as the blueprint for any new Grid instance, and that it would include the namespace Rows as a part of that.

So, in the Grid constructor, when I apply the new context of this to this.Rows, this.Rows would initially be a copy, not a reference, of the Grid.prototype.Rows blueprint, which belongs only to that instance.

In the Grid constructor, I thought I'd be modifying this.Rows, for that instance, to be bound to the context of this, not the prototype itself.

Post Answer

My additional thoughts were silly because I had forgotten that the prototype is referenced by all objects that inherit from it, rather than it being used as a blueprint for instance of the objects.

The fiddle here illustrates the point.

Community
  • 1
  • 1
Ash Clarke
  • 4,807
  • 1
  • 37
  • 48

1 Answers1

1

Because that is what a prototype is for: All of its members are the same for each instance. You could call this.Rows = Object.create(Grid.prototype.Rows); in your Grid init function, e.g., but you have to do it yourself. JavaScript does not know that you want a new instance for every Grid instance.

a better oliver
  • 26,330
  • 2
  • 58
  • 66
  • My thinking was that the `Grid.prototype` acts as the blueprint for any new `Grid` instance, and that it would include the namespace `Rows` as a part of that. So, when I apply the new context of `this` in the `Grid` function to `this.Rows`, `this.Rows` would initially be a copy, not a reference, of the `Grid.prototype.Rows` blueprint, which belongs only to that instance. In the `Grid` constructor, I thought I'd be modifying `this.Rows` for that instance to be bound to the context of `this`. – Ash Clarke Mar 12 '13 at 11:43
  • When you call `new Grid(id)` then you get an object with one property: id. Grid does not have an init function. It has a link to a prototype and the prototype has the init function. The init function is not copied to the Grid object, if you meant this by blueprint. – a better oliver Mar 12 '13 at 11:51
  • Ah I see, I think I have forgotten that the `prototype` is just a shared reference of, I suppose, static methods and that `prototype` functions are not cloned in to each instance. I don't know how I could have forgotten that >_ – Ash Clarke Mar 12 '13 at 11:54