如何用JS对象代理实现对象的私有属性
Jacshuo Lv3

今天我们来聊聊私有属性,在其他的高级语言中很容易能实现私有属性的功能,在JavaScript中怎么实现对象的私有属性呢?首先我们聊聊私有属性运用的需求场景,比如我们在对象里用 _ 符号开头的形式定义对象的私有属性,不希望外部环境读取私有属性,如下段代码所示:

1
2
3
4
5
let bankAccount = {
holderName: 'Joe',
currency: 'USD',
_balance: 1000
}

我们希望读取对象 _balance 的私有属性或删除对象的 _balance 属性,会有如下的提示:

1
2
3
4
// don't allow reading the balance
console.log(bankAccount._balance);
// don't allow deleting the property
delete _balance

那我们该如何实现呢?这时候我们可以使用 JS 代理,针对 _符号开头的私有属性进行特殊的逻辑处理(你也可以用其他的符号自定义私有属性),废话不多说,上代理的实现的代码逻辑,以下为代理拦截器方法的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
let proxyHandler = { 
has: (target, prop) => {
if(prop.startsWith(prefix)){
return false;
}
return prop in target
}, // 针对 in 方法的重写
ownKeys: target => {
return Reflect.ownKeys(target).filter(
prop => !prop.startsWith(prefix)
)
}, //针对 keys 方法的重写
get: (target, prop) => {
if(prop.startsWith(prefix)) {
return undefined;
}
return target[prop];
},
deleteProperty(target, prop) {
if (prop.startsWith('_')) {
return true; //私有属性不删除
} else {
delete target[prop];
return true;
}
}
}

接下来,我们来验证下上述代码是否可行:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
const hidePrivateFields = (target, prefix = "_") => { 
return new Proxy(target, proxyHandler)
};

let bankAccount = hidePrivateFields({
holderName: 'Joe',
currency: 'USD',
_balance: 1000
})

console.log(bankAccount._balance) // undefined
console.log('_balance' in bankAccount) //false
console.log(Object.keys(bankAccount)) // ['holderName', 'currency']
console.log(delete bankAccount._balance) // returns true, but does not delete the balance
  • 本文标题:如何用JS对象代理实现对象的私有属性
  • 本文作者:Jacshuo
  • 创建时间:2022-06-25 20:26:13
  • 本文链接:https://blog.imade.life/2022/06/25/如何用JS对象代理实现对象的私有属性/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!