要对Javascript对象封装的时候,常常遇到一种需求,就是隐藏其部分属性/方法,使之变成private作用域
const person = {
name: 'Tom'
};
person.name = 'John';
如果想要person调用的时候不能直接访问name,很自然的想到对name字段做setter/getter封装
const person = {
_name: 'Tom',
setName(name) {
this._name = name;
},
getName() {
return this._name;
}
};
person.setName('John');
// 这样的写法还是无法阻止对_name赋值
person._name = 'Kate';
因为JS语言不像Java/C#有private关键字,这样的方式并不能阻止对_name赋值。 那么我们有没有办法做到让_name完全无法访问?
方法一
对person对象进行再次封装输出
const person = {
_name: 'Tom',
setName(name) {
this._name = name;
},
getName() {
return this._name;
},
wrap() {
// 将可以被公开访问的方法/字段放在这里
const t = this;
return {
setName(name) {
t.setName(name);
},
getName() {
return t.getName();
}
};
}
};
const personWrap = person.wrap();
// 测试,personWrap中因为没有_name,所以只能通过setName访问
personWrap.setName('John');
console.log(personWrap.getName());
// 将重新封装的对象输出
export { personWrap };
方法二,使用Symbol
const _name = Symbol('name');
const person = {
[_name]: 'Tom',
setName(name) {
this[_name] = name;
},
getName() {
return this[_name];
}
};
// 导出之后的person因为拿不到Symbol('name')就无法再访问这个属性
export { person };
对比起来,第二种方式写法更简单代码量更少,但是要注意IE不支持Symbol,第一种方法的兼容性更好。