ES6中实现class私有属性

私有属性,即仅在当前class中有访问和修改权限,子类无法继承父类的私有属性。

下面为思考过程,若要看结果,直接跳到方案四

方案一:(错误示范)

let ClsA = (function(){
  let _x
  class Cls {
    setX = (x) => { _x = x }
    getX = () => { return _x }
  }
  return Cls
})()

let clsA = new ClsA
console.log(clsA)
// 输出:Cls {setX: ƒ, getX: ƒ}

cls.setX('clsA')
console.log(cls.getX())
// 输出:clsA

上述代码貌似实现了私有属性,但存在一个问题,具体看下面

let clsA2 = new ClsA

clsA2.setX('clsA2')

console.log(clsA2.getX())
// 输出:clsA2

console.log(clsA.getX())
// 输出:clsA2  ----> 之前的clsA中的私有变量也被改值了

方案二:

针对上面出现的问题,解决思路如下:

每个实例标记一个唯一的key,存储在privateData对象中

let ClsB = (function(){
  let privateData = {}, privateKey = 0
  class Cls {
      constructor(){ Object.defineProperty(this, '_x', { value: privateKey++ }) }
      setX = (x) => { privateData[this._x] = x }
      getX = () => { return privateData[this._x] }
  }
  return Cls
})()

let clsB = new ClsB, clsB1 = new ClsB

clsB.setX('clsB')

console.log(clsB.getX())
// 输出:clsB

clsB1.setX('clsB1')

console.log(clsB1.getX())
// 输出:clsB1

console.log(clsB.getX())
// 输出:clsB

方案三:

根据上面的思路,想到另外两个方案。1、“唯一key”,那么可以用Symbol;2、实例注销后,实例的“私有变量”依旧存在于privateData中,那么可以用WeakMap(其弱引用的特性可以在没有任何引用时进行垃圾回收)

下面是Symbol的代码方案:

let ClsC = (function(){
  let privateData = {}
  class Cls {
      constructor(){ Object.defineProperty(this, '_x', { value: Symbol() }) }
      setX = (x) => { privateData[this._x] = x }
      getX = () => { return privateData[this._x] }
  }
  return Cls
})()

let clsC = new ClsC, clsC1 = new ClsC

clsC.setX('clsC')

console.log(clsC.getX())
// 输出:clsC

clsC1.setX('clsC1')

console.log(clsC1.getX())
// 输出:clsC1

console.log(clsC.getX())
// 输出:clsC

方案四:

let ClsD = (function(){
  let privateData = new WeakMap
  class Cls {
      setX = (x) => { privateData.set(this, x) }
      getX = () => { return privateData.get(this) }
  }
  return Cls
})()

let clsD = new ClsD, clsD1 = new ClsD

clsD.setX('clsD')

console.log(clsD.getX())
// 输出:clsD

clsD1.setX('clsD1')

console.log(clsD1.getX())
// 输出:clsD1

console.log(clsD.getX())
// 输出:clsD

 

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