Javascript 如何使用 Traceur 在 ES6 类中实现私有方法
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/27849064/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to implement private method in ES6 class with Traceur
提问by Glen Swift
I use Traceur Compiler to have advantage with ES6 features now.
我现在使用 Traceur Compiler 来获得 ES6 特性的优势。
I want to implement this stuff from ES5:
我想从 ES5 实现这些东西:
function Animal() {
var self = this,
sayHi;
sayHi = function() {
self.hi();
};
this.hi = function() {/* ... */}
}
Currently traceur does not support privateand publickeywords (from harmony). And ES6 class syntax does not allow to use simple var(or let) statements in class body.
目前 traceur 不支持private和public关键字(来自和谐)。ES6 类语法不允许在类主体中使用简单var(或let)语句。
The only way that I am find is to simulate privates before class declaration. Something like:
我发现的唯一方法是在类声明之前模拟私有。就像是:
var sayHi = function() {
// ... do stuff
};
class Animal {
...
It is better then nothing but as expected you can not pass correct thisto private method without apply-ing or bind-ing it every time.
最好什么都没有,但正如预期的那样,如果每次都this没有apply-ing 或bind-ing就无法将正确的方法传递给私有方法。
So, is there any possibility to use private data in ES6 class compatible with traceur compiler?
那么,是否有可能在与 traceur 编译器兼容的 ES6 类中使用私有数据?
回答by alexpods
There are no private, publicor protectedkeywords in current ECMAScript 6 specification.
当前的ECMAScript 6 规范中没有private, publicorprotected关键字。
So Traceur does not support privateand public. 6to5 (currently it's called "Babel") realizes this proposalfor experimental purpose (see also this discussion). But it's just proposal, after all.
所以 Traceur 不支持private和public。6to5(目前称为“Babel”)为实验目的实现了这个提议(另请参阅此讨论)。但这毕竟只是提议。
So for now you can just simulate private properties through WeakMap(see here). Another alternative is Symbol- but it doesn't provide actual privacy as the property can be easily accessed through Object.getOwnPropertySymbols.
所以现在你可以通过WeakMap(见这里)模拟私有属性。另一种选择是Symbol- 但它不提供实际隐私,因为可以通过Object.getOwnPropertySymbols.
IMHO the best solution at this time - just use pseudo privacy. If you frequently use applyor callwith your method, then this method is very object specific. So it's worth to declare it in your class just with underscore prefix:
恕我直言,此时最好的解决方案 - 只需使用伪隐私。如果您经常使用apply或call与您的方法一起使用,那么此方法是非常特定于对象的。所以值得在你的类中用下划线前缀声明它:
class Animal {
_sayHi() {
// do stuff
}
}
回答by Max
You can always use normal functions:
您始终可以使用正常功能:
function myPrivateFunction() {
console.log("My property: " + this.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
myPrivateFunction.bind(this)();
}
}
new MyClass(); // 'My property: myProp'
回答by Marcelo Lazaroni
Although currently there is no way to declare a method or property as private, ES6 modules are not in the global namespace. Therefore, anything that you declare in your module and do not export will not be available to any other part of your program, but will still be available to your module during run time. Thus, you have private properties and methods :)
尽管目前无法将方法或属性声明为私有,但ES6 模块不在全局命名空间中。因此,您在模块中声明但未导出的任何内容将无法用于程序的任何其他部分,但在运行时仍可用于您的模块。因此,您拥有私有属性和方法:)
Here is an example
(in test.jsfile)
这是一个示例(在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;
In another file
在另一个文件中
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
回答by Maxmaxmaximus
You can use Symbol
您可以使用符号
var say = Symbol()
function Cat(){
this[say]() // call private methos
}
Cat.prototype[say] = function(){ alert('im a private') }
P.S. alexpods is not correct. he get protect rather than private, since inheritance is a name conflict
PS alexpods 不正确。他得到保护而不是私有,因为继承是名称冲突
Actually you can use var say = String(Math.random())instead Symbol
其实你可以用var say = String(Math.random())符号代替
IN ES6:
在 ES6 中:
var say = Symbol()
class Cat {
constructor(){
this[say]() // call private
}
[say](){
alert('im private')
}
}
回答by Son JoungHo
I hope this can be helpful. :)
我希望这会有所帮助。:)
I. Declaring vars, functions inside IIFE(Immediately-invoked function expression), those can be used only in the anonymous function. (It can be good to use "let, const" keywords without using 'var' when you need to change code for ES6.)
一、在IIFE(Immediately-invoked function expression) 中声明 vars,函数,这些只能在匿名函数中使用。(当您需要更改 ES6 代码时,最好使用“let, const”关键字而不使用“var”。)
let Name = (function() {
const _privateHello = function() {
}
class Name {
constructor() {
}
publicMethod() {
_privateHello()
}
}
return Name;
})();
II. WeakMap object can be good for memoryleak trouble.
二、WeakMap 对象可以很好地解决内存泄漏问题。
Stored variables in the WeakMap will be removed when the instance will be removed. Check this article. (Managing the private data of ES6 classes)
当实例被移除时, WeakMap 中存储的变量将被移除。检查这篇文章。(管理 ES6 类的私有数据)
let Name = (function() {
const _privateName = new WeakMap();
})();
III. Let's put all together.
三、让我们把所有的放在一起。
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"
回答by jamsesso
As alexpods says, there is no dedicated way to do this in ES6. However, for those interested, there is also a proposal for the bind operatorwhich enables this sort of syntax:
正如 alexpods 所说,在 ES6 中没有专门的方法来做到这一点。但是,对于那些感兴趣的人,还有一个关于启用这种语法的绑定运算符的建议:
function privateMethod() {
return `Hello ${this.name}`;
}
export class Animal {
constructor(name) {
this.name = name;
}
publicMethod() {
this::privateMethod();
}
}
Once again, this is just a proposal. Your mileage may vary.
再一次,这只是一个提议。你的旅费可能会改变。
回答by Nicola Pedretti
Have you considered using factory functions? They usually are a much better alternative to classes or constructor functionsin Javascript. Here is an example of how it works:
您是否考虑过使用工厂函数?它们通常是Javascript 中类或构造函数的更好替代品。以下是它如何工作的示例:
function car () {
var privateVariable = 4
function privateFunction () {}
return {
color: 'red',
drive: function (miles) {},
stop: function() {}
....
}
}
Thanks to closures you have access to all private functions and variabels inside the returned object, but you can not access them from outside.
由于闭包,您可以访问返回对象内的所有私有函数和变量,但您无法从外部访问它们。
回答by Patrick Graham
As Marcelo Lazaronihas already said,
正如马塞洛·拉扎罗尼 (Marcelo Lazaroni) 已经说过的,
Although currently there is no way to declare a method or property as private, ES6 modules are not in the global namespace. Therefore, anything that you declare in your module and do not export will not be available to any other part of your program, but will still be available to your module during run time.
尽管目前无法将方法或属性声明为私有,但 ES6 模块不在全局命名空间中。因此,您在模块中声明但未导出的任何内容将无法用于程序的任何其他部分,但在运行时仍可用于您的模块。
But his example didn't show how the private method could access members of the instance of the class. Maxshows us some good examples of how access instance members through binding or the alternative of using a lambda method in the constructor, but I would like to add one more simple way of doing it: passing the instance as a parameter to the private method. Doing it this way would lead Max's MyClass to look like this:
但是他的例子没有显示私有方法如何访问类实例的成员。Max向我们展示了如何通过绑定访问实例成员或在构造函数中使用 lambda 方法的替代方法的一些很好的示例,但我想添加一种更简单的方法:将实例作为参数传递给私有方法。这样做会导致 Max 的 MyClass 看起来像这样:
function myPrivateFunction(myClass) {
console.log("My property: " + myClass.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
}
testMethod() {
myPrivateFunction(this);
}
}
module.exports = MyClass;
Which way you do it really comes down to personal preference.
你怎么做真的取决于个人喜好。
回答by kofifus
I came up with what I feel is a much better solution allowing:
我想出了我认为更好的解决方案,允许:
no need for 'this._', that/self, weakmaps, symbols etc. Clear and straightforward 'class' code
private variables and methods are really private and have the correct 'this' binding
No use of 'this' at all which means clear code that is much less error prone
public interface is clear and separated from the implementation as a proxy to private methods
allows easy composition
不需要“this._”、that/self、weakmaps、symbols 等。清晰直接的“类”代码
私有变量和方法是真正私有的,并且具有正确的“this”绑定
根本不使用“this”,这意味着代码清晰,不易出错
公共接口清晰,并且作为私有方法的代理与实现分离
允许轻松组合
with this you can do:
有了这个,你可以这样做:
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>
see Newfor the code and more elaborate examples including constructor and composition
请参阅新代码和更详细的示例,包括构造函数和组合

