Страницы

Поиск по вопросам

понедельник, 30 декабря 2019 г.

JavaScript, приватные переменные

#javascript


Как можно создать в классе (ecma6 class) приватную переменную?
    


Ответы

Ответ 1



В es6 такой возможности нет. Многие думают, что классы es6 это какая-то новая конструкция или реализация , нет. Это обычный , новый синтаксис для старого доброго прототипного наследования. class Animal { constructor() { this.name = "dog" } say() { alert("gaf") } } То же самое, что и function Animal() { this.name = "dog" } Animal.prototype.say = function () { alert("gaf") } Поэтому приватных методов в классе не реализовано, вам придется решать эту проблему самому. Как? Например, через замыкание const Animal = function () { let privateProp = "i am private"; class Animal { constructor() { this.name = "dog"; } // гетеры и сеттеры для свойства get PrivateProp() { return privateProp } set PrivateProp(value) { privateProp = value } } return new Animal(); }; let dog = new Animal(); dog.privateProp; // приватное свойство dog.privateProp = "new private prop"; // меняем приватное свойство Тут методы get/set просто для примера, в реальности скорее всего их не будет, если уже переменная приватная. Тут get/set единственные способы достучатся до privateProp, больше никак, уберете get/set privateProp станет настоящим приватным способом. UPD Чуть ошибся, переменная создавалась бы одна для всех экземпляров, как написали в комментарии, поправил ответ. Теперь всегда будет создаваться свой экземпляр приватной переменной

Ответ 2



Для приватных свойств надо использовать замыкания и символы. const Animal = (function () { const privatePropSymbol = Symbol("privateProp"); class Animal { // гетеры и сеттеры для свойства get PrivateProp() { return this[privatePropSymbol]; } set PrivateProp(value) { this[privatePropSymbol] = value } } Animal.prototype[privatePropSymbol] = "default value"; return Animal; })(); Фокус в том, что два символа с одинаковым названием остаются двумя разными символами - поэтому не имея переменной privatePropSymbol внешний код не сможет получить к нему доступ.

Ответ 3



А ВОТ ТАК (при чем так можно делать уже 200 лет отроду): ES6: var say = Symbol() class Cat { constructor(){ this[say]() // call private } [say](){ alert('im private') } } ES5: var say = Math.random() // pollyfill Symbol() function Cat(){ this[say]() // call private methods } Cat.prototype[say] = function(){ alert('im a private') } Пример использования ES6: var handlers = Symbol() class EventEmitter { constructor(){ this[handlers] = [] } on(handler){ this[handlers].push(handler) } emit(){ for(let handler of this[handlers]) handler() } } class Cat extends EventEmitter { } var q = new Cat() q.on // function q.emit // function q.handlers // undefined cuz PRIVATE ;) И не обязательно больше учить названия свойств из реализации класса, таких как внутреннее свойство handlers, боясь их случайно перекрыть в классах наследниках. Использую приватные уже 6 лет. И ни каких проблем с утечками. Не понимаю людей которые говорят что в яваскрипте приватных нет. Наслаждайтесь, и поменьше слушайте всяких неумех ;)

Комментариев нет:

Отправить комментарий