views:

290

answers:

2

I'm using the Prototype.js (from www.prototypejs.org) library to create classes which are extended by subclasses. I'm having trouble using arrays within instances of these classes though. I've made an example to illustrate this:

var SuperClass = Class.create({
    initialize: function(id) {
     this.id = id;
    }
});

var SubClass = Class.create(SuperClass, {
    items: [],

    add: function(arg) {
     this.items[this.items.length] = arg;
    },

    initialize: function($super, id) {
     $super(id);
    }
});

var a = new SubClass("a");
var b = new SubClass("b");

a.add("blah");
alert(a.id + ": " + a.items.length);
alert(b.id + ": " + b.items.length);

The problem here is that both the first and the second alert will indicate that their respective objects have 1 item in their items array, even though I only added an item to object a. Primitive data types work correctly (as is shown by the id property correctly showing up) but arrays just won't work. It also doesn't matter if I move the items array and the add method to the superclass, I already tried.

Is there some way of getting this to work? Is this a bug in Prototype or is this something that is in JavaScript's nature? :-)

A: 

The members of the object literal passed to Class.create are added to the prototype of SubClass, so all your objects will share the items-array. You can mend the situation by moving the items-definition to your constructor:

var SubClass = Class.create(SuperClass, {

    add: function(arg) {
        this.items[this.items.length] = arg;
    },

    initialize: function($super, id) {
        $super(id);
        this.items = [];
    }
});
Magnar
Wow, quick answer. And the right one too! Thanks a lot, really appreciate it.
Jerry
A: 

I'm not a Prototype user but... JavaScript is a prototypal language. That means it uses prototypal inheritance. In other words object inherit from objects, or object inherit state and behavior from other objects. In your case, both object a and b will inherit from that object declared in literal notation in Class.create(SuperClass, {}) so items will be shared between the two because every instance of MyClass inherits from that object literal.

Here's some example:

var Foo = function (name) {
    this.name = name;
};

var Bar = function () {};
Bar.prototype = new Foo("John");

var a = new Bar;
var b = new Bar;

alert(a.name); // John
alert(b.name); // John
Ionuț G. Stan