ES6中没有官方的私有属性语法,但是我们可以使用以下几种方式来模拟实现:
1. 命名约定
将私有属性命名以下划线“_”开头,约定为私有属性,外部不应直接访问。这种方式不需要额外的代码,只需要在类中按照约定命名私有属性即可。例如:
class MyClass {
constructor() {
this._privateProperty = '私有属性';
}
getPrivateProperty() {
return this._privateProperty;
}
}
这种方式的缺点是没有实质性的保护作用,外部仍然可以通过直接访问属性来获取私有属性的值。
2. Symbol私有属性
使用Symbol作为私有属性的键,这样外部就无法直接访问私有属性。例如:
const _privateKey = Symbol('私有属性');
class MyClass {
constructor(privateValue) {
this[_privateKey] = privateValue;
}
getPrivateValue() {
return this[_privateKey];
}
}
这种方式可以保护私有属性不被外部直接访问,但是如果外部知道了Symbol值,仍然可以访问私有属性。
3. WeakMap私有属性
使用WeakMap存储私有属性,外部无法直接访问WeakMap中的属性。例如:
const privateMap = new WeakMap();
class MyClass {
constructor(privateValue) {
privateMap.set(this, privateValue);
}
getPrivateValue() {
return privateMap.get(this);
}
}
这种方式可以保护私有属性不被外部直接访问,而且外部无法获取WeakMap的键。
4. 闭包实现私有属性
使用闭包将私有属性封装在类中,外部无法访问。例如:
class MyClass {
constructor(privateValue) {
this.getPrivateValue = function() {
return privateValue;
};
}
}
这种方式可以保护私有属性不被外部直接访问,但是每创建一个实例都会新建一个函数,会占用额外的内存空间。
5. Proxy实现私有属性
使用Proxy代理类的属性访问,可以实现私有属性。例如:
const privateHandler = {
get(target, prop) {
if (prop.startsWith('_')) {
throw new Error('私有属性,禁止访问!');
}
return target[prop];
},
set(target, prop, value) {
if (prop.startsWith('_')) {
throw new Error('私有属性,禁止赋值!');
}
target[prop] = value;
return true;
}
};
class MyClass {
constructor() {
this.publicProperty = '公有属性';
this._privateProperty = '私有属性';
return new Proxy(this, privateHandler);
}
}
这种方式可以保护私有属性不被外部直接访问,而且可以控制是否允许赋值。但是这种方式需要额外的代码来实现。
综上所述,以上方法均可以实现类的私有属性,具体选择哪种方式取决于应用场景和个人偏好。