2010-06-07 16 views
5

Próbuję zdefiniować klasę javascript za pomocą właściwości tablicowej i jej podklasy. Problemem jest to, że wszystkie przypadki podklasy jakoś „zakładowego” nieruchomości tablicy:Dziedziczenie i tablice 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? 

Jak widać nie mam ten problem z prymitywnych typów danych ... jakieś sugestie?

+1

Zobacz http://stackoverflow.com/questions/1485824/javascript -inheritance-objects-declaration-in-constructor-is-shared-between-inst –

Odpowiedz

1

Jedyne, co mogę wymyślić to to, że tablice są wspólnymi referencjami. Powinno istnieć oczywiste rozwiązanie, ponieważ ten klasyczny kod OOP jest cały czas implementowany w JavaScript.

4

Po napisaniu Test2.prototype = new Test() tworzona jest pojedyncza instancja Test z pojedynczą instancją macierzy współużytkowaną przez każdą instancję Test2.

Dlatego wszystkie instancje Test2 współużytkują tę samą tablicę.

Możesz rozwiązać ten problem, wywołując konstruktor bazy Test z konstruktora Test2, który utworzy nową instancję tablicy dla każdej instancji Test2.

Na przykład:

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

innego, raczej nieeleganckie, alternatywą jest przeniesienie kodu inicjalizacji z konstruktora do metody i wywołać ją z obu konstruktorów:

// 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 dla jasności. – jvenema

1

JavaScript nie posiada klasyczny system dziedziczenia, ma prototypowy system dziedziczenia. W technice JavaScript nie ma więc pojęcia "klasy".

Obiekty dziedziczą z innych obiektów (tzw. Obiektu prototypowego), a nie z klas abstrakcyjnych. Jedną z głównych konsekwencji jest to, że jeśli kilka obiektów ma ten sam prototyp i jeden z tych obiektów zmienia atrybut zdefiniowany w prototypie, to zmiana ta jest natychmiast skuteczna dla wszystkich innych obiektów.

Próba użycia dziedziczenia JavaScriptu tak, jakby opierała się na zajęciach, zwykle powoduje duże bóle głowy, ponieważ cały czas znajdujesz tego typu problemy.

Wiem, że to naprawdę nie odpowiada na twoje pytania, ale na wysokim poziomie, polecam ci objąć dziedziczenie prototypowe, zamiast próbować użyć "pseudo-klas". Nawet jeśli początkowo wygląda dziwnie, twój kod będzie znacznie bardziej niezawodny i nie stracisz czasu na próbę zrozumienia dziwnych błędów, takich jak ten, spowodowanych dziwnym łańcuchem prototypów.

Zobacz wideo, w którym Douglas Crockford wyjaśnia dziedziczenie, jest dostępne online na stronie Yahoo UI Theatre. To zmieniło moje zaprogramowane w JavaScript :)

http://video.yahoo.com/watch/111585/1027823 (Link do pierwszej części)

http://developer.yahoo.com/yui/theater/ (wszystkie filmy)