我现在使用 Traceur Compiler 来利用 ES6 功能。
我想从 ES5 实现这些东西:
function Animal() {
var self = this,
sayHi;
sayHi = function() {
self.hi();
};
this.hi = function() {/* ... */}
}
目前 Traceur 不支持
private
和 public
关键字(来自 Harmony)。 ES6 类语法不允许在类主体中使用简单的 var
(或 let
)语句。
我发现的唯一方法是在类声明之前模拟私有。比如:
var sayHi = function() {
// ... do stuff
};
class Animal {
...
总比什么都不做要好,但正如预期的那样,如果每次都没有
this
-ing 或 apply
-ing ,则无法将正确的 bind
传递给私有方法。
那么,是否有可能在与traceur编译器兼容的ES6类中使用私有数据?
当前
ECMAScript 6 规范中没有
private
、public
或 protected
关键字。
所以 Traceur 不支持
private
和 public
。 6to5(目前称为“Babel”)出于实验目的实现了此提案(另请参阅此讨论)。但这毕竟只是提议。
所以现在你可以通过
WeakMap
模拟私有属性(参见here)。另一种选择是 Symbol
- 但它不提供实际的隐私,因为可以通过 Object.getOwnPropertySymbols
轻松访问该财产。
恕我直言,目前最好的解决方案是使用伪隐私。如果您经常在您的方法中使用
apply
或 call
,那么此方法是非常特定于对象的。因此,值得在您的类中使用下划线前缀来声明它:
class Animal {
_sayHi() {
// do stuff
}
}
您始终可以使用正常功能:
function myPrivateFunction() {
console.log("My property: " + this.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
myPrivateFunction.bind(this)();
}
}
new MyClass(); // 'My property: myProp'
虽然目前无法将方法或属性声明为私有,但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') }
附注alexpods 不正确。他得到保护而不是私有,因为继承是名称冲突
其实你可以用
var say = String(Math.random())
代替 Symbol
在 ES6 中:
var say = Symbol()
class Cat {
constructor(){
this[say]() // call private
}
[say](){
alert('im private')
}
}
我希望这能有所帮助。 :)
我。在IIFE(立即调用函数表达式)中声明变量、函数,这些只能在匿名函数中使用。 (当您需要更改 ES6 代码时,最好使用“let, const”关键字而不使用“var”。)
let Name = (function() {
const _privateHello = function() {
}
class Name {
constructor() {
}
publicMethod() {
_privateHello()
}
}
return Name;
})();
二. WeakMap 对象可以很好地解决内存泄漏问题。
当实例被删除时,WeakMap 中存储的变量也会被删除。检查这篇文章。 (管理ES6类的私有数据)
let Name = (function() {
const _privateName = new WeakMap();
})();
三.让我们把所有的放在一起吧。
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"
您考虑过使用工厂函数吗? 它们通常是 Javascript 中类或构造函数的更好的替代品。 以下是其工作原理的示例:
function car () {
var privateVariable = 4
function privateFunction () {}
return {
color: 'red',
drive: function (miles) {},
stop: function() {}
....
}
}
借助闭包,您可以访问返回对象内的所有私有函数和变量,但无法从外部访问它们。
bind 运算符 的建议,它支持这种语法:
function privateMethod() {
return `Hello ${this.name}`;
}
export class Animal {
constructor(name) {
this.name = name;
}
publicMethod() {
this::privateMethod();
}
}
再次强调,这只是一个建议。您的里程可能会有所不同。
Marcelo Lazaroni 已经说过的那样,
虽然目前无法将方法或属性声明为私有,但 ES6 模块并不位于全局命名空间中。因此,您在模块中声明且未导出的任何内容都将不可用于程序的任何其他部分,但在运行时仍可用于您的模块。但是他的示例没有显示私有方法如何访问类实例的成员。
function myPrivateFunction(myClass) {
console.log("My property: " + myClass.prop);
}
class MyClass() {
constructor() {
this.prop = "myProp";
}
testMethod() {
myPrivateFunction(this);
}
}
module.exports = MyClass;
具体采用哪种方式取决于个人喜好。
function Counter(seed=0) {
// define public interface
const self = Object.assign(this, {
advance, // advance counter and get new value
reset, // reset value
value // get value
})
// init private state
// any parameters passed to the function itself are also part of it's private state
let count=seed;
// call constructor if needed
constructor()
//logic (private & public methods)
function constructor() { console.log('new Counter') }
function advance() { return ++count }
function reset(newCount) { count=(newCount || 0) }
function value() { return count }
return self
}
let counter=new Counter()
console.log(counter instanceof Counter) // true
counter.reset(100)
console.log('Counter next = '+counter.advance()) // 101