JS - 面向对象 - 私有属性

面向对象

在日常业务中,我们总是需要使用 对象 将一个事物抽象出来,而考虑安全等因素,又需要对其中部分属性进行隐藏显示,在面对对象的 java、 C 等编程语言,有语法规范设定,而在 JavaScript 中没有, 目前只能通过变通方法模拟实现。

举栗子

在 《Eloquent_JavaScript》 习题中,题目要求通过解锁获取到 _content,同时说明了不予许直接访问 _content ,如下:

    let box = {
        locked: true ,      // 放这不大安全哦
        unlock: function () {
            this.locked = false; 
        }, 
        lock: function () {
            this.locked = true; 
        }, 
        _content: [],       // 放这不大安全哦
        get content () {
            if (this.locked) throw new Error(" Locked !");
            return this._content;
        } 
    }

相比解题,可能大部分人也会顺带想想,得让 _content 私有化,只能由内部指定的方法访问才行,不然像这样就很尴尬了

    // 直接重新指向,破坏内部数据
    box._content = null

    // 再正常访问 ,啥都没了
    box.unlock()
    box.content     // =>  null 

    // 或者
    box.locked = false
    box.content     // =>  null 

闭包

还是闭包,毕竟就为储存变量而生的嘛,引申下就是对外(函数)变量 私有 ,对内 公开

    let box = (function(){
      let locked = true     
      let _content = []      // 私有属性作为 闭包变量 存储,只能由内部函数获取
      return {
        unlock: function () {
          locked = false; 
        }, 
        lock: function () {
          locked = true; 
        }, 
        get content () {     // 唯一对外开放的可以访问到 content 属性的方法
          if (locked) throw new Error(" Locked !");
          return _content;
        } 
      }
    })()

再来试试

    box._content = null

    //一切正常,因为上面已经无法指向 _content 了
    box.unlock()    
    box.content     // =>  [] 

    // 同理
    box.locked = false
    box.content     // =>  [] 

上面的是对象实例,要用扩展到类来实现 私有属性 呢
常见的构造函数

  // 常用显式展示 
    function Person(name, age) {
        this.name = name
        this.age = age
    }

    name = 'ice'
    age = 18
    p1 = new Person(name,age)         // => {name: "ice", age: 18}

当我需要这属性不再显示的表现,只能 固定接口 访问时

  // 常用隐式展示 
    function Person(name, age) {
        this.name = name
        this.getAge = function() {
            return age - 5
        }
    }
    p2 = new Person(name,age)         // => {name: "ice", getAge: ƒ}

功能上可行,但在性能有个缺点,因为我们是直接在 构造函数 Person 内再创建一个函数(闭包),以此隐藏属性,而每一次构建实例也都对多创建这一个函数,所以一定程度上内存消耗产生影响。

WeakMap 销毁

在 MDN 上 关于 WeakMap 有句这样的描述:

每个键对自己所引用对象的引用是 "弱引用" ,这意味着,如果没有其他引用和该键引用同一个对象,这个对象将会被当作垃圾回收。

对此,结合下上面的解决办法,缓解内存问题

  // 目前最优解 (占内存更小,一旦访问指针丢失,则会自动销毁)
  let Person = function(){
  let wm = new WeakMap()

  return class Person {
    constructor(name,age) {
      this.name = name
      wm.set(this, {
        age: age
      })
    }

    get age() {
      return wm.get(this).age
    }

  }
}()

你可能感兴趣的:(JS - 面向对象 - 私有属性)