2015-12-29 4 views
6

Примечание: Я уже прошел через ниже SO Вопросы и 7 ответов (как сейчас) о Symbols, WeekMaps и Карты, пожалуйста, прочитайте полный вопрос, прежде чем голосовать: Private properties in JavaScript ES6 classes
Статья: https://esdiscuss.org/topic/es7-property-initializersМодификаторы доступа (Private, Protected) в ES6

Ниже мой Simple Class, который содержит частные, государственные и защищенные свойства и методы.

'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

Я экземпляра объекта и вызов открытый метод, который работает, как ожидалось.

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

работает, как ожидалось.

Теперь мой вопрос. Я знаю, что в спецификации ES6 есть несколько таких вещей, как Symbol, каков текущий обходной путь для защиты и частные переменные/методы, работающие над классами ES6.

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

Я хочу, чтобы это свойство и метод, чтобы быть видимыми только в своем классе.

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

Я хочу, чтобы это свойство и метод, чтобы быть видимыми в своем классе и внутри классах, проходящих его.

Обхода лучшего решения/для достижения такого поведения ценятся

+4

Если вы уже читали о Символах и WeakMap, что еще вам нужно знать? –

+0

Я прошел через те, но ожидал, что пример будет ответом на ограничение и расширенный класс. –

+2

ES6 классы не имеют конфиденциального/защищенного намеренно: [см. Здесь] (http://stackoverflow.com/a/22158732/ 2509123) WeakMap/Symbols является более обходным путем для добавления их в классы ES6, но классы ES6 - это больше способ определить методы, чем повторять «классические» классы OO на таких языках, как Java и C# –

ответ

8

Частных свойств

В ES6 (и раньше), все реализации частной собственности полагаются на closure.

Люди have been doing it еще до того, как JavaScript имеет версии. WeakMap - это просто вариация, которая устраняет необходимость в новой области и новых функциях для каждого нового объекта за счет скорости доступа.

Символ - это вариация ES6, которая скрывает атрибут от общих операций, таких как простой доступ к свойствам или 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 ] ]);

Как видно выше, можно обойти по Object.getOwnPropertySymbols(). Несмотря на свое существование, я всегда выбираю символ над WeakMap. Код чище, проще, меньше работает gc, и (я думаю) более эффективен.

Я лично избегаю class, тоже. Object.create намного проще. Но это выходит за рамки.


Защищенные свойства

Защищенные свойства, по своей природе, требует выполнения функции, чтобы узнать объект кода вызова, чтобы судить, должен ли он быть предоставлен доступ.

Это невозможно в JS, а не потому, что ES6 имеет no real class, но из-за вызывающего контекста является simply unavailable.

Из-за variousspecialnatures JavaScript, для обозримых будущих охраняемых объектов остается невозможным.

В качестве альтернативы ...


свойства пакета

Некоторые языки имеют полу-защищенные свойства, иногда называемый «пакет частной», где метод/свойство доступно для членов в том же модуль/пакет.

ES6 может реализовать его с закрытием. Это точно так же, как и код частной собственности выше - просто поделитесь областью и ее символами с несколькими прототипами.

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