Наследование классов в Prototype.js и массивах

Я использую библиотеку Prototype.js (из www.prototypejs.org) для создания классов, которые расширяются подклассами. Однако у меня возникают проблемы с использованием массивов в экземплярах этих классов. Я сделал пример, чтобы проиллюстрировать это:

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);

Проблема здесь в том, что и первое, и второе предупреждение будут указывать, что соответствующие объекты имеют 1 элемент в массиве элементов, хотя я добавил элемент только к объекту a. Примитивные типы данных работают корректно (о чем свидетельствует правильное отображение свойства id), но массивы просто не будут работать. Также не имеет значения, если я перенесу массив элементов и метод добавления в суперкласс, я уже пробовал.

Есть ли способ заставить это работать? Это ошибка в Prototype или это особенность JavaScript? :-)


person Jela    schedule 27.08.2009    source источник


Ответы (2)


Члены литерала объекта, переданного в Class.create, добавляются к прототипу подкласса, поэтому все ваши объекты будут совместно использовать массив элементов. Вы можете исправить ситуацию, переместив определение элементов в свой конструктор:

var SubClass = Class.create(SuperClass, {

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

    initialize: function($super, id) {
        $super(id);
        this.items = [];
    }
});
person Magnar    schedule 27.08.2009
comment
Вау, быстрый ответ. И правильный тоже! Большое спасибо, очень ценю это. - person Jela; 27.08.2009

Я не являюсь пользователем Prototype, но... JavaScript — это язык-прототип. Это означает, что он использует прототипное наследование. Другими словами, объект наследует от объектов или объект наследует состояние и поведение от других объектов. В вашем случае оба объекта a и b будут наследовать от этого объекта, объявленного в литеральной нотации в Class.create(SuperClass, {}), поэтому items будет совместно использоваться ими двумя, поскольку каждый экземпляр MyClass наследуется от этого литерала объекта.

Вот пример:

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
person Ionuț G. Stan    schedule 27.08.2009