Как реализовать частный метод в классе ES6 с помощью Traceur
Я использую Traceur Compiler, чтобы иметь преимущество с функциями ES6.
Я хочу реализовать этот материал с ES5:
function Animal() {
var self = this,
sayHi;
sayHi = function() {
self.hi();
};
this.hi = function() {/* ... */}
}
В настоящее время traceur не поддерживает private
и public
ключевые слова (из гармонии). И синтаксис класса ES6 не позволяет использовать простые выражения var
(или let
) в классе тела.
Единственный способ, которым я нахожу, - имитировать приватов перед объявлением класса. Что-то вроде:
var sayHi = function() {
// ... do stuff
};
class Animal {
...
Лучше тогда ничего, но, как и ожидалось, вы не можете передать правильный this
приватный метод без apply
-ing или bind
-в его каждый раз.
Итак, есть ли возможность использовать частные данные в классе ES6, совместимом с компилятором traceur?
Ответы
Ответ 1
В текущей спецификации ECMAScript 6 нет private
, public
или protected
.
Итак, Traceur не поддерживает private
и public
. 6to5 (в настоящее время он называется "Babel" ) реализует это предложение для экспериментальной цели (см. Также эту дискуссию). Но это просто предложение, в конце концов.
Итак, теперь вы можете просто имитировать частные свойства через WeakMap
(см. здесь). Другой альтернативой является Symbol
- но это не подразумевает никакой конфиденциальности, поскольку свойство легко можно получить через Object.getOwnPropertySymbols
.
ИМХО лучшее решение в это время - просто используйте псевдо-конфиденциальность. Если вы часто используете apply
или call
с помощью своего метода, этот метод очень специфичен для объекта. Поэтому стоит объявить его в своем классе только с префиксом подчеркивания:
class Animal {
_sayHi() {
// do stuff
}
}
Ответ 2
Вы всегда можете использовать обычные функции:
function myPrivateFunction() {
console.log("My property: " + this.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
myPrivateFunction.bind(this)();
}
}
new MyClass(); // 'My property: myProp'
Ответ 3
Хотя в настоящее время нет способа объявить метод или свойство как частные, модули ES6 не входят в глобальное пространство имен. Таким образом, все, что вы объявляете в своем модуле и не экспортируете, не будет доступно ни для какой другой части вашей программы, но все равно будет доступно вашему модулю во время выполнения. Таким образом, у вас есть частные свойства и методы:)
Вот пример
(в файле test.js
)
function tryMe1(a) {
console.log(a + 2);
}
var tryMe2 = 1234;
class myModule {
tryMe3(a) {
console.log(a + 100);
}
getTryMe1(a) {
tryMe1(a);
}
getTryMe2() {
return tryMe2;
}
}
// Exports just myModule class. Not anything outside of it.
export default myModule;
В другом файле
import MyModule from './test';
let bar = new MyModule();
tryMe1(1); // ReferenceError: tryMe1 is not defined
tryMe2; // ReferenceError: tryMe2 is not defined
bar.tryMe1(1); // TypeError: bar.tryMe1 is not a function
bar.tryMe2; // undefined
bar.tryMe3(1); // 101
bar.getTryMe1(1); // 3
bar.getTryMe2(); // 1234
Ответ 4
Вы можете использовать Symbol
var say = Symbol()
function Cat(){
this[say]() // call private methos
}
Cat.prototype[say] = function(){ alert('im a private') }
P.S. alexpods неверен. он получает защиту, а не частный, поскольку наследование - это конфликт имен
На самом деле вы можете использовать var say = String(Math.random())
вместо Symbol
В ES6:
var say = Symbol()
class Cat {
constructor(){
this[say]() // call private
}
[say](){
alert('im private')
}
}
Ответ 5
Как сообщает alexpods, в ES6 нет специального способа сделать это. Однако для желающих есть предложение для оператора который позволяет использовать этот вид синтаксиса:
function privateMethod() {
return `Hello ${this.name}`;
}
export class Animal {
constructor(name) {
this.name = name;
}
publicMethod() {
this::privateMethod();
}
}
Еще раз, это всего лишь предложение. Ваш пробег может отличаться.
Ответ 6
Надеюсь, это может быть полезно.:)
я. Объявление vars, функции внутри IIFE (выражение с мгновенным вызовом функции), они могут использоваться только в анонимной функции. (Можно использовать слова "let, const" без использования "var", когда вам нужно изменить код для ES6.)
let Name = (function() {
const _privateHello = function() {
}
class Name {
constructor() {
}
publicMethod() {
_privateHello()
}
}
return Name;
})();
II. Объект WeakMap может быть полезен для проблем с памятью.
Сохраненные переменные в WeakMap будут удалены, когда экземпляр будет удален. Проверьте эту статью. (Управление частными данными классов ES6)
let Name = (function() {
const _privateName = new WeakMap();
})();
III. Пусть все вместе.
let Name = (function() {
const _privateName = new WeakMap();
const _privateHello = function(fullName) {
console.log("Hello, " + fullName);
}
class Name {
constructor(firstName, lastName) {
_privateName.set(this, {firstName: firstName, lastName: lastName});
}
static printName(name) {
let privateName = _privateName.get(name);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
printName() {
let privateName = _privateName.get(this);
let _fullname = privateName.firstName + " " + privateName.lastName;
_privateHello(_fullname);
}
}
return Name;
})();
var aMan = new Name("JH", "Son");
aMan.printName(); // "Hello, JH Son"
Name.printName(aMan); // "Hello, JH Son"
Ответ 7
Я придумал то, что я чувствую, это гораздо лучшее решение, позволяющее:
-
не нужно "this._", это/я, слабые карты, символы и т.д. Четкий и простой код класса
-
частные переменные и методы действительно конфиденциальны и имеют правильную привязку 'this'
-
Не использовать 'this' вообще, что означает четкий код, который намного меньше подвержен ошибкам
-
открытый интерфейс прозрачен и отделен от реализации как прокси-сервер частным методам
-
позволяет легко составить
с этим вы можете:
function Counter() {
// public interface
const proxy = {
advance, // advance counter and get new value
reset, // reset value
value // get value
}
// private variables and methods
let count=0;
function advance() {
return ++count;
}
function reset(newCount) {
count=(newCount || 0);
}
function value() {
return count;
}
return proxy;
}
let counter=Counter.New();
console.log(counter instanceof Counter); // true
counter.reset(100);
console.log('Counter next = '+counter.advance()); // 101
console.log(Object.getOwnPropertyNames(counter)); // ["advance", "reset", "value"]
<script src="https://cdn.rawgit.com/kofifus/New/7987670c/new.js"></script>
Ответ 8
Считаете ли вы использование функций factory?
Обычно они являются гораздо лучшей альтернативой классам или функциям конструктора в Javascript.
Вот пример того, как он работает:
function car () {
var privateVariable = 4
function privateFunction () {}
return {
color: 'red',
drive: function (miles) {},
stop: function() {}
....
}
}
Благодаря закрытию вы получаете доступ ко всем частным функциям и переменным внутри возвращаемого объекта, но вы не можете получить к ним доступ извне.
Ответ 9
Как Марсело Лазарони уже сказал,
Хотя в настоящее время нет способа объявить метод или свойство частным, модули ES6 не входят в глобальное пространство имен. Таким образом, все, что вы заявляете в своем модуле и не экспортируете, не будет доступно ни для какой другой части вашей программы, но все равно будет доступно вашему модулю во время выполнения.
Но в его примере не показано, как частный метод может обращаться к членам экземпляра класса. Max показывает нам некоторые хорошие примеры того, как члены экземпляра доступа через привязку или альтернативу использования лямбда-метода в конструкторе, но я хотел бы добавить еще один простой способ сделать это: передать экземпляр в качестве параметра для частного метода. Выполнение этого способа привело бы Max MyClass выглядеть следующим образом:
function myPrivateFunction(myClass) {
console.log("My property: " + myClass.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
}
testMethod() {
myPrivateFunction(this);
}
}
module.exports = MyClass;
Каким образом вы это делаете, это действительно сводится к личным предпочтениям.