2015-12-29 18 views
6

Uwaga: ja już przeszedł poniżej SO Pytania i 7 odpowiedzi (jak na razie) około Symbols, WeekMaps i Mapy, proszę przeczytać cały pytanie zanim głosowania: Private properties in JavaScript ES6 classes
artykułu: https://esdiscuss.org/topic/es7-property-initializersModyfikatory dostępu (private, protected) w ES6

Poniżej jest moje Simple Class która zawiera prywatne, publiczne i chronione właściwości i metody.

'use strict'; 
 
    class MyClass { 
 
    constructor() { 
 
     this.publicVar = 'This is Public Variable'; 
 
     this.privateVar = 'This is Private Variable'; 
 
     this.protectedVar = 'This is Protected Variable'; 
 
    } // Public Constructor Method. 
 
    
 
    publicMethod() { 
 
     console.log(' Accessing this.publicVar: ', this.publicVar); 
 
     console.log(' Accessing this.privateVar: ', this.privateVar); 
 
     console.log(' Accessing this.protectedVar: ', this.protectedVar); 
 
     return 'Its Public Method' 
 
    } // Public Method. 
 

 
    privateMethod() {return 'Its Private Method'} // Private Method. 
 
    protectedMethod() {return 'Its Protected Method'} // Protected Method. 
 

 
    foo() { 
 
     this.publicMethod(); 
 
     this.privateMethod(); 
 
     this.protectedMethod(); 
 
    } // Public Method 
 
    } // end class

mam instancji obiektu, oraz wywołanie metody publiczny, który działa zgodnie z oczekiwaniami.

let MyObject = new MyClass; 
MyObject.foo(); // Works fine. 
console.log(MyObject.publicVar); // Works 
console.log(MyObject.publicMethod()); // Works 

działa zgodnie z oczekiwaniami.

Teraz moje pytanie. Jestem świadomy, że kilka rzeczy, takich jak Symbol, znajduje się w specyfikacji ES6, jakie jest obecne obejście, aby uzyskać chronione i prywatne zmienne/metody działające na klasach ES6.

console.log(MyObject.privateVar); // Works 
console.log(MyObject.privateMethod()); // Works 

Chcę tę właściwość i sposób, aby były widoczne tylko w swojej własnej klasie.

console.log(MyObject.protectedVar); // Works 
console.log(MyObject.protectedMethod()); // Works 

Chcę tę właściwość i sposób, aby były widoczne w swojej klasie i wewnątrz klas rozszerzając go.

Obejście/lepszym rozwiązaniem, aby osiągnąć to zachowanie jest doceniana

+4

Jeśli już czytałeś o Symbolach i Słabej Mapie, co jeszcze musisz wiedzieć? –

+0

Przeszedłem przez te, ale oczekując przykładu jako odpowiedzi na ograniczenie i rozszerzenie zakresu klasy, –

+2

Klasy ES6 nie mają prywatnych/chronionych umyślnie: [patrz tutaj] (http://stackoverflow.com/a/22158732/ 2509123) WeakMap/Symbols to więcej sposobów na dodanie ich do klas ES6, ale klasy ES6 są bardziej sposobem definiowania metod niż replikowanie "klasycznych" klas OO w językach takich jak Java i C# –

Odpowiedz

8

właściwości prywatnych

W ES6 (i wcześniej) wszystkie implementacje własności prywatnej polegać na closure.

Osoby have been doing it jeszcze przed JavaScript ma wersje. WeakMap to odmiana, która eliminuje potrzebę nowego zakresu i nowych funkcji dla każdego nowego obiektu, kosztem szybkości dostępu.

Symbol jest odmianą ES6, która ukrywa atrybut przed typowymi operacjami, takimi jak prosty dostęp do właściwości lub for in.

var MyClass; 
 
(() => { 
 
    // Define a scoped symbol for private property A. 
 
    const PropA = Symbol('A'); 
 
    // Define the class once we have all symbols 
 
    MyClass = class { 
 
    someFunction() { 
 
     return "I can read " + this[ PropA ]; // Access private property 
 
    } 
 
    } 
 
    MyClass.prototype[ PropA ] = 'Private property or method'; 
 
})(); 
 

 
// function in the closure can access the private property. 
 
var myObject = new MyClass(); 
 
alert(myObject.someFunction()); 
 

 
// But we cannot "recreate" the Symbol externally. 
 
alert(myObject[ Symbol('A') ]); // undefined 
 

 
// However if someone *really* must access it... 
 
var symbols = Object.getOwnPropertySymbols(myObject.__proto__); 
 
alert(myObject[ symbols[ 0 ] ]);

Jak widać powyżej, można obejść przez Object.getOwnPropertySymbols(). Mimo istnienia zawsze wybieram symbol nad WeakMap. Kod jest czystszy, prostszy, mniej pracy z GC i (myślę) bardziej wydajny.

Osobiście też unikam class. Object.create jest znacznie prostsze. Ale to jest poza zakresem.


Chronione właściwości

Chronione właściwości, ze swej natury wymaga wykonywania funkcji wiedzieć przedmiot kodu wywołującego, aby ocenić, czy należy przyznać dostęp.

Jest to niemożliwe w JS, ponieważ nie ma no real class ES6, ale dlatego, że rozmówcy kontekście jest simply unavailable.

Ze względu na variousspecialnatures kodu JavaScript, ponieważ przewidywalne przyszłe chronione właściwości pozostaną niemożliwe.

Alternatywnie ...


właściwości opakowania

Niektóre języki mają właściwości częściowo chroniony, czasami zwany „pakiet prywatne”, gdzie metoda/Obiekt jest dostępny dla członków w tym samym moduł/pakiet.

ES6 może zaimplementować to z zamknięciem. To jest dokładnie to samo, co powyższy kod własności prywatnej - wystarczy udostępnić zakres i jego symbole wielu prototypom.

Jest to niepraktyczne, ponieważ wymaga zdefiniowania całego modułu w tym samym zamkniętym zakresie, tj. W jednym pliku. Ale jest to jednak opcja.

Powiązane problemy