如何在ES6的class上实现私有属性

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);
  }
}

这种方式可以保护私有属性不被外部直接访问,而且可以控制是否允许赋值。但是这种方式需要额外的代码来实现。

综上所述,以上方法均可以实现类的私有属性,具体选择哪种方式取决于应用场景和个人偏好。

你可能感兴趣的:(前端,ES6,面试,es6,前端)