面向对象
在日常业务中,我们总是需要使用 对象 将一个事物抽象出来,而考虑安全等因素,又需要对其中部分属性进行隐藏显示,在面对对象的 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}
![](https://img.haomeiwen.com/i12160095/a9cac91a748db2e0.png)
当我需要这属性不再显示的表现,只能 固定接口 访问时
// 常用隐式展示
function Person(name, age) {
this.name = name
this.getAge = function() {
return age - 5
}
}
p2 = new Person(name,age) // => {name: "ice", getAge: ƒ}
![](https://img.haomeiwen.com/i12160095/e602f3d014c2aba1.png)
功能上可行,但在性能有个缺点,因为我们是直接在 构造函数 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
}
}
}()
网友评论