1.命名實現(xiàn)
第一個方法是使用特定的命名約定來表示屬性應(yīng)該被視為私有。通常以下劃線作為屬性名稱的前綴(例如 _name )。但這并不能阻止變量被訪問或修改,而是依賴于開發(fā)者之間的相互約定,認(rèn)為這個變量應(yīng)該被視私有屬性。
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
getName() {
return this._name;
}
setName(newName) {
this._name = newName;
}
}
const test = new Person('張三',24)
2.閉包實現(xiàn)
第二個方法是利用js提供的強大的閉包,閉包背后的想法是將數(shù)據(jù)封裝在調(diào)用時創(chuàng)建的函數(shù)作用域內(nèi),但是從內(nèi)部返回函數(shù)的結(jié)果,從而使這一作用域無法從外部訪問。
const Person = () => {
let name = '張三';
let age = 24;
return {
getName() {
return name;
},
setName(newName) {
name = newName;
}
}
}
const test1 = Person();
test1.getName() //張三
test1.setName('李四');
test1.getName()// 李四
3.Symbol+ 閉包實現(xiàn)
第三個方法是利用es6提供的新特性Symbol與閉包一起使用,(如果你還不熟悉Symbol,請參閱 ECMAScript 6 入門)
const person2 = (name, age) => {
const _name = Symbol('name');
const _age = Symbol('age');
return class Person {
constructor() {
this[_name] = name;
this[_age] = age;
}
getName() {
return this[_name];
}
setName(newName) {
this[_name] = newName;
}
}
}
const Test2 = person2('張三', 24);
const test3 = new Test2();
console.log('test3', test3);
4.*Proxy + 方法一
第四個方法是利用es6提供的新特性Proxy與方法一一起使用((如果你還不熟悉Proxy,請參閱 ECMAScript 6 入門)),使用Proxy進行攔截+命名式的代碼可以讓這些私有變量在類外部訪問受限。
const person3 = (name, age) => {
class Person {
constructor(name, age) {
this._name = name;
this._age = age;
}
getName() {
return this._name;
}
setName(newName) {
this._name = newName;
}
}
const handle = {
get(target, key) {
if (key[0] === '_') {
throw new Error('該屬性為私有屬性')
} else if (key === 'toJSON') {
const obj = {}
//防止JSON.stringify 序列化 如果一個被序列化的對象擁有 toJSON 方法,那么該 toJSON 方法就會覆蓋該對象默認(rèn)的序列化行為:不是那個對象被序列化,而是調(diào)用 toJSON 方法后的返回值會被序列化。
for (const key in target) {
if (key[0] !== '_') {
obj[key] = Reflect.get(target, key);
}
}
return obj;
}
return Reflect.get(target, key);
},
set(target, key, value) {
if (key[0] === '_') {
throw new Error('該屬性為私有屬性')
}
Reflect.set(target, key, value);
},
// 禁止 for in 枚舉
getOwnPropertyDescriptor(target, key) {
const desc = Reflect.getOwnPropertyDescriptor(target, key);
if (key[0] === '_') {
desc.enumerable = false;
}
return desc;
}
}
return new Proxy(new Person(name, age), handle);
}
const test4 = person3('張三', 24);
test4._namr // error
JSON.stringify(test4); // {};
完整的代碼實例:https://github.com/summer789/studyJS/blob/master/privateProperty.html