Наследование JavaScript и массивы

Я пытаюсь определить класс JavaScript со свойством массива и его подкласс. Проблема состоит в том, что все экземпляры подкласса так или иначе "совместно используют" свойство массива:

// class Test
function Test() {
    this.array = [];
    this.number = 0;
} 

Test.prototype.push = function() {
   this.array.push('hello');
   this.number = 100;
}

// class Test2 : Test
function Test2() {
}

Test2.prototype = new Test();

var a = new Test2();
a.push(); // push 'hello' into a.array

var b = new Test2();
alert(b.number); // b.number is 0 - that's OK
alert(b.array); // but b.array is containing 'hello' instead of being empty. why?

Поскольку Вы видите, что у меня нет этой проблемы с примитивными типами данных... Какие-либо предложения?

5
задан Inespe 7 June 2010 в 13:37
поделиться

4 ответа

Когда вы пишете Test2.prototype = new Test () , вы создаете единственный экземпляр Test с одним экземпляром массива, который используется совместно каждым экземпляром Test2 .

Следовательно, все экземпляры Test2 используют один и тот же массив.

Вы можете решить эту проблему, вызвав конструктор base Test из конструктора Test2 , который создаст новый экземпляр массива для каждого экземпляра Test2 .

Например:

function Test2() {
    Test.call(this);
}
4
ответ дан 14 December 2019 в 01:02
поделиться

Другая, довольно неэлегантная альтернатива - перенести код инициализации из конструктора в метод и вызывать его из обоих конструкторов:

// class Test
function Test() {
  this.init();
} 

Test.prototype.init = function() {
    this.array = [];
    this.number = 0;
};

Test.prototype.push = function() {
   this.array.push('hello');
   this.number = 100;
};

// class Test2 : Test
function Test2() {
  this.init();
}

Test2.prototype = new Test();
3
ответ дан 14 December 2019 в 01:02
поделиться

Я могу думать только о том, что массивы - это общие ссылки. Должно быть очевидное решение, поскольку такой классический код ООП постоянно реализуется в Javascript.

1
ответ дан 14 December 2019 в 01:02
поделиться

JavaScript не имеет классической системы наследования, он имеет прототипическую систему наследования. Поэтому в JavaScript технически не существует понятия "Класс".

Объекты наследуются от других объектов (так называемый прототип объекта), а не от абстрактных классов. Одним из важных последствий этого является то, что если несколько объектов имеют один и тот же прототип и один из этих объектов изменяет атрибут, определенный в прототипе, то это изменение немедленно вступает в силу для всех остальных объектов.

Попытка использовать наследование JavaScript так, как если бы оно было основано на классах, обычно вызывает большую головную боль, потому что вы постоянно сталкиваетесь с такого рода проблемами.

Я знаю, что это не совсем отвечает на ваши конкретные вопросы, но на высоком уровне я рекомендую вам принять прототипическое наследование вместо того, чтобы пытаться использовать "псевдоклассы". Даже если поначалу это выглядит странно, ваш код будет намного надежнее, и вы не будете терять время, пытаясь понять странные ошибки вроде этой, вызванные странной цепочкой прототипов.

Посмотрите это видео, где Дуглас Крокфорд объясняет наследование, оно доступно онлайн на сайте Yahoo UI Theater. Оно изменило мой подход к программированию на JavaScript :)

http://video.yahoo.com/watch/111585/1027823 (ссылка на первую часть)

http://developer.yahoo.com/yui/theater/ (для всех видео)

1
ответ дан 14 December 2019 в 01:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: