Наследование Javascript и Массивы - PullRequest
5 голосов
/ 07 июня 2010

Я пытаюсь определить класс 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?

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

Ответы [ 4 ]

4 голосов
/ 07 июня 2010

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

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

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

Например:

function Test2() {
    Test.call(this);
}
3 голосов
/ 07 июня 2010

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

// 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();
1 голос
/ 07 июня 2010

JavaScript не имеет классической системы наследования, он имеет прототипную систему наследования. Так что в JavaScript технически нет понятия «класс».

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

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

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

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

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

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

1 голос
/ 07 июня 2010

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...