ES6实现类的私有变量的几种写法

723 阅读2分钟

闭包实现类的私有变量方式

私有变量不共享。

通过 new 关键字 person 的构造函数内部的 this 将会指向 Tom,开辟新空间,再次全部执行一遍,

class Person{  
        constructor(name){ 
            let _num = 100; 

            this.name = name;
            this.getNum = function(){
               return _num;
            } 
            this.addNum = function(){
                return ++_num
            } 
        }
    }
    
    const tom  = new Person('tom')
    const jack  = new Person('jack')
    tom.addNum() 
    console.log(tom.getNum())  //101
    console.log(jack.getNum())  //100 

私有变量可共享

为避免每个实力都生成了一个新的私有变量,造成是有变量不可共享的问题,我们可以将这个私有变量放在类的构造函数到外面,继续通过闭包来返回这个变量。

const Person = (function () {
        let _num = 100;

        return class _Person {
            constructor(name) {
                this.name = name; 
            }
            addNum() {
              return ++_num
            }
            getNum() {
              return _num
            } 
        }
    })() 

    const tom = new Person('tom')
    const jack = new Person('jack') 
    tom.addNum()
    console.log(tom.getNum())  //101
    console.log(jack.getNum())  //101 

那这样的话,如果两种方法混合使用,那就可以拥有可共享和不可共享的两种私有变量。

缺点:实例化时会增加很多副本,比较耗内存。

Symbol实现类的私有变量方式

symbol 简介:

创建一个独一无二的值,所有 Symbol 两两都不相等,创建时可以为其添加描述Symble("desc"),目前对象的健也支持 Symbol 了。

const name = Symbol('名字')
const person = { // 类名
    [name]:'www',
    say(){
        console.log(`name is ${this[name]} `) 
    } 
}  
person.say()
console.log(name)

使用Symbol为对象创建的健无法迭代和Json序列化,所以其最主要的作用就是为对象添加一个独一无二的值。 但可以使用getOwnProporitySymbols()获取Symbol.

缺点:新语法浏览器兼容不是很广泛。

symbol 实现类的私有变量

推荐使用闭包的方式创建 Symbol 的的引用,这样就可以在类的方法区获得此引用,避免方法都写在构造函数,每次创建新实例都要重新开辟空间赋值方法,造成内存浪费。

const Person = (function () {
  let _num = Symbol('_num:私有变量');
  
  return class _Person {
    constructor(name) {
      this.name = name;
      this[_num] = 100
    }
    addNum() {
      return ++this[_num]
    }
    getNum() {
      return this[_num]
    } 
  }
})()

const tom = new Person('tom')
const jack = new Person('jack')

console.log(tom.addNum()) //101 
console.log(jack.getNum()) //100

通过 weakmap 创建私有变量

MDN 简介

image.png

实现:

const Parent = (function () {
  const privates = new WeakMap();

  return class Parent {
    constructor() {
      const me = {
        data: "Private data goes here"
      };
      privates.set(this, me);
    }
    getP() {
      const me = privates.get(this);
      return me
    }
  } 
})()

let p = new Parent()
console.log(p)
console.log(p.getP())

总结

综上 weakmap 的方式来实现类似私有变量省内存,易回收,又能够被更多的浏览器兼容,也是最推荐的实现方法。