2010-06-07 4 views
5

Я пытаюсь определить класс javascript с свойством array и его подклассом. Проблема заключается в том, что все экземпляры подкласса как-то «акция» свойство массива:Наследование и массивы 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? 

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

+1

См http://stackoverflow.com/questions/1485824/javascript -inheritance-objects-declaration-in-constructor-are-shared-between-inst –

ответ

1

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

4

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

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

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

Например:

function Test2() { 
    Test.call(this); 
} 
3

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

// 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(); 
+0

+1 для ясности. – jvenema

1

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

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

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

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

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

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

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

Смежные вопросы