2011-01-22 8 views
7

W JavaScript, chciałbym zdefiniować klasę z klasą wewnętrzną (lub zagnieżdżoną). W ramach wewnętrznej klasy chciałbym móc uzyskać dostęp do instancji nadrzędnej. Jak mogę to zrobić wydajnie?JavaScript, wewnętrzne klasy i jak skutecznie uzyskać dostęp do zakresu nadrzędnego

Niektóre kod pokaże co mam na myśli. Załóżmy, że zdefiniowanie klasy, MyType1, która odsłania kilka właściwości i jedną funkcję, SayHello:

(function(){ 
    MyType1 = function(name){ 
     this.TypeName = "MyType1"; 
     this.Name = name; 
    }; 

    MyType1.prototype.SayHello = function() { 
     say(this.Name + " says hello..."); 
    }; 
})(); 

Ok, teraz, wychodząc stamtąd, chcę dodać „wewnętrzną klasę” do MyType1, więc dodam kilka nowych kod tak, że wygląda tak:

(function(){ 
    MyType1 = function(name){ 
     this.TypeName = "MyType1"; 
     this.Name = name; 
     var parentName = name; 
     this.Child = function(name) { 
      this.Description = parentName + "'s child, " + name; 
     }; 

     this.Child.prototype.Introduce = function() { 
      say(this.Description + ", greets you..."); 
     }; 
    }; 

    MyType1.prototype.SayHello = function() { 
     say(this.Name + " says hello..."); 
    }; 
})(); 

teraz mogę korzystać z tych klas tak:

var x = new MyType1("Victor"); 
x.SayHello(); 

var c = new x.Child("Elizabeth"); 
c.Introduce(); 

, że wszystko działa. Ale definiuje nową funkcję Child (lub typu, jeśli chcesz) dla każdego wystąpienia MyType1. Chciałbym uzyskać dostęp do zakresu klasy nadrzędnej, bez uciekania się do tej nieefektywności. coś takiego:

(function(){ 
    MyType2 = function(name){ 
     this.TypeName = "MyType2"; 
     this.Name = name; 
     this.Prop1 = 1872; 
     var parentName = name; 
    }; 

    MyType2.prototype.SayHello = function() { 
     say(this.Name + " says hello..."); 
    }; 

    var c1 = function(name) { 
     this.Description = parentName + "'s child, " + name; 
     //    ^^ no go! ^^ 
    }; 

    c1.prototype.Introduce = function() { 
     say(this.Description + ", greets you..."); 
    }; 

    MyType2.prototype.Child = c1; 

})(); 

Ale to nie działa. Zmienna parentName jest poza zakresem, oczywiście.

Czy istnieje skuteczny sposób dla instancji Child (w konstruktorze lub w dowolnej klasie), aby uzyskać dostęp do instancji nadrzędnej (MyType2)?


wiem, że mogę określić klasę dziecka do bycia niezależnym, nie zagnieżdżone klasy, to w ctor za to, po prostu przekazać instancji nadrzędnej. Ale tworzy N odwołań do instancji nadrzędnej, jednej dla każdej instancji podrzędnej. To wydaje się być nieskutecznością, której chciałbym uniknąć.

dzięki za wszelkie wskazówki.


EDIT - powodem chcę dziecko miało dostęp do instancji nadrzędnej, jest to, że dominująca posiada obiekt, który jest dość drogie, aby utworzyć - coś w rodzaju połączenia db - i chciałbym dziecko, aby móc to wykorzystać.

+3

Ugh, jeszcze więcej nadużywania Javascriptu do wprowadzenia nonsensów "OOP". Ten język nie ma klas: jeśli chcesz, użyj czegoś, co robi! –

+1

Może się to okazać przydatne: http://blog.niftysnippets.org/2009/09/simple-efficient-supercalls-in.html Jest to zestaw funkcji pomocniczych (i ich wyjaśnienie), które zapewniają proste, ale wydajne, tworzenia "podklas" "klas" utworzonych przez prototypowe dziedziczenie. Wygląda na to, że robisz to dość ręcznie, więc może cię to uratować. –

+2

@Tomalek: Masz całkowitą rację, oczywiście JavaScript nie ma klas. Jest zorientowany obiektowo i ma dziedziczenie. –

Odpowiedz

4

Prawdopodobnie pomogłoby Ci to, gdybyś poradził sobie z takimi pojęciami jak "typ", "klasa" itp. Podczas pracy z javascript. W javascript nie ma różnicy między "typem", "klasą", "funkcją", "instancją" lub "obiektem" - jest to "obiekt" do samego końca.

Ponieważ każdy "typ" jest "obiektem" i można go modyfikować, nie uzyskuje się niczego w rodzaju silnie napisanych przyrostów wydajności, które można uzyskać z języka Java lub C++, ponownie wykorzystując definicję jednego typu. Pomyśl o "nowym" operatorze w javascript jako o czymś w rodzaju "sklonuj definicję i wywołaj konstruktora", po czym definicja instancji wciąż może zostać zmieniona.

Więc idź z pierwszym, działającym przykładem: nie osiągniesz żadnych korzyści, wykonując coś innego.

1

Jedynym sposobem mogę myśleć jest przekazanie w obiektu nadrzędnego do konstruktora dziecko:

MyType2.Child = function (parent, name) { 
    this.parent = parent; 
    this.name = name; 
    this.Description = this.parent.name + "'s child, " + name; 
}; 

I instancji go:

var x = new MyType2("Victor"); 

var c = new MyType2.Child(x, "Elizabeth"); 

Moje uzasadnienie jest to, że większy sens że konstruktor Child jest "statyczną" właściwością MyType2, zamiast instancyjnego obiektu x w twoim przykładzie, ponieważ mówimy tutaj o typach, które są s ame we wszystkich instancjach MyType2.

+0

Zrobiłem to wcześniej, tylko po to, aby umożliwić obsługę kodu - DRY. –

2

To właśnie wpadłem po wielu godzinach:

var Parent = function() { 
    this.name = "Parent"; 

    this.Child = Child; 
    this.Child.prototype.parent = this; 
} 

var Child = function() { 

} 

var parent = new Parent(); 
var child = new parent.Child(); 

console.log(child.parent.name); 

W ten sposób można utworzyć wystąpienia jak wielu rodziców, jak chcesz, z ich Childs pod spodem, a każdy przypadek dziecko będzie miało dostęp do niego jest instancja rodzic poprzez zmienną rodzic.

0

nie testowałem, ale powinieneś być w stanie korzystać z tego JSON:

//code here 
var number = { 
    real : { 
     value : 0, //default value 
     rational : { 
      integer : { 
       isNegative : false, 
       value : 0 //default value 
      } 
     } 
    }, 
    imaginary : { 
     //code 
    } 
}; 

var number2 = Object.create(number.rational.integer.prototype); 

Teraz może być wiele problemów z tym, funkcjonalne i stylistyczne. Ale jest to alternatywa dla innych przedstawionych tutaj podejść.

Powiązane problemy