js类中私有变量与私有方法的实现

今天详细了解了下这方面的,算是做个记录

es5中实现

主要还是使用闭包实现,Object.defineProperty不能实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var People = (function(){
function privateFunc(){
console.log('privateFunc')
}
var privateVar = 'privateVar';
function People(){
this.publicVar = '1';
}
People.prototype.publicFunc = function(){
privateFunc.call(this);
}
return People;
})()
var people = new People();
Object.keys(people); //['publicVar']
people.publicFunc(); //'private test'

es6中实现

采用闭包+symbol实现

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
var People = (function(){
var s1 = Symbol('privatekey');
var s2 = Symbol('privatekey')
class People{
constructor(){
this[s1] = () => {console.log('privateFunc')};
this[s2] = 'privateVar';
}
publicFunc(){
console.log(this[s1]());
console.log(this[s2]);
}
}
return People;
})()
var people = new People();
Object.keys(people); //['publicVar']
people.publicFunc(); //'private test'

symbol是es新添加的一种数据类型(之前有六种:null, undefined, 数字,字符串,布尔,对象),每次都能生成一个唯一不同的值。它有一个很重要的特点:它虽然不是私有属性,但是不会出现在for…in,for…of循环中,也不会被Object.keys()、Object.getOwnPropertyNames()返回。所以直接定义在this上并不会被枚举到。
但是这也不是万无一失,有两个api可以查询到symbol属性:Object.getOwnPropertySymbols和Reflect.ownKeys。但是这基本能满足需求了

1
2
people[Object.getOwnPropertySymbols(people)[0]](); //'privateFunc'
people[Object.getOwnPropertySymbols(people)[1]]; //'privateVar'