如何用Traceur实现ES6类中的私有方法

我现在使用Traceur编译器来使用ES6function。

我想从ES5实现这个东西:

function Animal() { var self = this, sayHi; sayHi = function() { self.hi(); }; this.hi = function() {/* ... */} } 

目前traceur不支持privatepublic关键字( 来自和谐 )。 而ES6类语法不允许在类体中使用简单的var (或let )语句。

我发现的唯一方法是在类声明之前模拟私有。 就像是:

 var sayHi = function() { // ... do stuff }; class Animal { ... 

如果不出意料的话,不如预期的那样,如果没有每次applybind它,都不能将其正确地传递给私有方法。

那么,有没有可能在与traceur编译器兼容的ES6类中使用私有数据呢?

目前的ECMAScript 6规范中没有privatepublicprotected关键字。

所以Traceur不支持privatepublic 。 6to5(现在叫做“Babel”)实现了这个实验目的(另见这个讨论 )。 但毕竟这只是build议。

所以现在你可以通过WeakMap来模拟私有属性(见这里 )。 另一个select是Symbol – 但它并不意味着任何隐私,因为属性可以通过Object.getOwnPropertySymbols轻松获得。

恕我直言,在这个时候最好的解决scheme – 只使用伪隐私。 如果您经常使用applycall方法,那么这个方法是非常特定的。 所以值得在你的类中用下划线前缀声明它:

 class Animal { _sayHi() { // do stuff } } 

你可以随时使用正常的function:

 function myPrivateFunction() { console.log("My property: " + this.prop); } class MyClass() { constructor() { this.prop = "myProp"; myPrivateFunction.bind(this)(); } } new MyClass(); // 'My property: myProp' 

尽pipe目前没有办法将方法或属性声明为私有,但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 

你可以使用符号

 var say = Symbol() function Cat(){ this[say]() // call private methos } Cat.prototype[say] = function(){ alert('im a private') } 

PS alexpods是不正确的。 他得到的是保护而不是私人的,因为inheritance是名称冲突

其实你可以使用var say = String(Math.random())来代替Symbol

在ES6:

 var say = Symbol() class Cat { constructor(){ this[say]() // call private } [say](){ alert('im private') } } 

正如alexpods所说,在ES6中没有专门的方法来做到这一点。 但是,对于那些感兴趣的,也有一个绑定运算符的build议,使这种语法:

 function privateMethod() { return `Hello ${this.name}`; } export class Animal { constructor(name) { this.name = name; } publicMethod() { this::privateMethod(); } } 

再一次,这只是一个build议。 你的旅费可能会改变。

我希望这可以有所帮助。 🙂

I.在IIFE(即时调用的函数expression式)中声明variables,函数,这些函数只能在匿名函数中使用。 (当需要更改ES6的代码时,可以使用“let,const”关键字而不使用“var”。)

 let Name = (function() { const _privateHello = function() { } class Name { constructor() { } publicMethod() { _privateHello() } } return Name; })(); 

II。 WeakMap对象可以很好的处理内存泄漏的麻烦。

在删除实例时,WeakMap中的存储variables将被删除。 检查这篇文章。 ( pipe理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" 

你有没有考虑使用工厂function? 它们通常是Javascript中类或构造函数的更好select 。 这是一个如何工作的例子:

 function car () { var privateVariable = 4 function privateFunction () {} return { color: 'red', drive: function (miles) {}, stop: function() {} .... } } 

由于closures,你可以访问返回对象内的所有私有函数和variables,但是你不能从外部访问它们。

我想出了我觉得是一个更好的解决scheme,允许:

  • 不需要'this._',那个/ self,weakmaps,symbols等等。清晰而直接的'class'代码

  • 私有variables和方法真的是私有的,并且具有正确的“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> 

正如马塞洛·拉扎罗尼(Marcelo Lazaroni )所说,

虽然目前没有办法将方法或属性声明为私有,但ES6模块不在全局名称空间中。 因此,在模块中声明并且不导出的任何内容都不会被程序的任何其他部分使用,但在运行时仍然可用。

但是他的例子并没有显示私有方法如何访问类实例的成员。 Max给我们展示了如何通过绑定访问实例成员或者在构造函数中使用lambda方法的替代方法,但是我想添加一个更简单的方法:将实例作为parameter passing给私有方法。 这样做会导致Max的MyClass看起来像这样:

 function myPrivateFunction(myClass) { console.log("My property: " + myClass.prop); } class MyClass() { constructor() { this.prop = "myProp"; } testMethod() { myPrivateFunction(this); } } module.exports = MyClass; 

你做什么这真的归结为个人喜好。