重生之——我用WeakMap和Symbol缔造专属于我的金丝雀~~~【使用WeakMap和Symbol实现属性私有】

#今日份大脑爆炸#

#看完下面内容包你更进一步理解WeakMap!#

不想属性被外人看见?不想是个人都能看见你的属性?那就看看WeakMap,帮你轻松实现你的目标!

1.WeakMap:

第一版:
        //WeakMap管理私有属性:

    const host = new WeakMap()
        //这里创建了一个WeakMap实例host,用于存储每个User实例的host属性

    class User {
      constructor(url) {
        host.set(this, url)
        // 注意:WeakMap 的键必须是对象,且set方法必须有两个参数。
      }
      set host(url) {
        if (!/^https?:\/\//i.test(url)) {
          throw new Error('地址错误')
        }
        host.set(this, url)
        // 不明就里会犯的错误:this[host] = url  
        //错误原因:host是WeakMap的实例,不应该直接作为对象的属性键使用。
      }
      get host() {
        return host.get(this)
        // return this[host] 错误同上。
      }
    }
    let hd = new User()
    hd.host = 'https://www.houdunren.com'
    console.log(hd.host);
    let xj = new User('https://www.bilibili.com')
    console.log(xj.host);

你可能会好奇:明明在外面就可以更改属性值,那怎么能叫私有属性呢?在真正的开发中,上面代码块中的类以及WeakMap定义的host都会被模块化,外面并不能直接访问,只会给出部分对外接口。

如果想要实现更多属性私有化,那么可以进行如下操作:

第二版:
    const properties = new WeakMap()
    class Common {
      constructor() {
        properties.set(this, { address: 'https://www.xupt.com' })
          //将地址属性先放进对象中,进行初始化
      }
      set address(url) {
        if (!/^https?:\/\//i.test(url)) {
          throw new Error('地址错误')
        }
        properties.set(this, { ...properties.get(this), address: url })
        //设置地址属性时,先获取全部的属性,将地址属性添加进去,以免出现错误
      }
      get address() {
        return properties.get(this).address
        //获取属性值时,按照对象属性的获取方法
      }
    }

    class Admin extends Common {
       //extends在这里就相当于起继承作用,即:Admin继承Common
      constructor(name) {
        super()
       //注意:不要忘了添加super()
      properties.set(this, {  ...properties.get(this),name})
        //this.name = name,如果这样写就直接把属性加到实例上,不满足需求。
      }
      set name(name) {
        properties.set(this, { ...properties.get(this), name })
      }
      get name() {
        return properties.get(this).name
      }

    }
    let h = new Admin('pink')
    h.address = 'https://www.houdunren.com'
    console.log(h.address);
    let pink = new Admin('houdunren')
    pink.address = 'https://www.js.com'
    console.log(pink.address);
    console.log(pink.name);

2.Symbol:

第一版:
   
    const host = Symbol()
    class User {
      constructor(host) {
        this[host] = host
          //注意:这里用中括号,因为host是变量,引用时需要用中括号。如果直接写.host,就相当于直接给实例添加属性host。
      }
      set host(value) {
        if (!/^https?:\/\//i.test(value)) {
          throw new Error('地址错误')
        }
        this[host] = value
      }
      get host() {
        return this[host]
      }

    }
    let hd = new User('houdunrne')
    hd.host = 'https://www.bilibili.com'
    console.log(hd.host);//https://www.bilibili.com

Symbol 是 JavaScript 中的一种原始数据类型,它表示独一无二的值。
这里使用 Symbol 作为对象属性的键,是为了避免属性名冲突,因为 Symbol 键是唯一的,不会与其他属性名重复。

第二版
    const properties = Symbol()
    class Father {
      constructor(host) {
        this[properties] = {}
        this[properties].host = host
      }
      set host(value) {
        if (!/^https?:\/\//i.test(value)) {
          throw new Error('地址错误')
        }
        this[properties].host = value
        //注:这里并不会重复调用:
        //在 setter 方法中,this[properties].host = value 不会重复调用 setter 方法,
        // 因为这里是直接访问 this[properties] 对象的 host 属性,而不是通过对象的 host 属性访问器来设置值。
        // 只有当通过 d.host = value 这种方式访问对象的 host 属性时,才会触发 setter 方法。
      }
      get host() {
        return this[properties].host
      }

    }

    class Admin extends Father {
      // Admin 类继承自 Father 类。
      constructor(name) {
        super()
        this[properties].name = name
      }
      get name() {
        return this[properties].name
      }

    }
    let d = new Admin('houdunrne')
    d.host = 'https://www.houdunren.com'
    console.log(d.name);
    console.log(d.host);

相信各位前端煲仔们会有所收获哦~

下次再见!

你可能感兴趣的:(JS,前端,javascript,开发语言,WeakMap,class,类,Symbol)