-
Notifications
You must be signed in to change notification settings - Fork 24
/
Copy path02-private-properties.js
59 lines (55 loc) · 2.08 KB
/
02-private-properties.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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
// 02 - Hiding private properties
function privateProps(obj, filterFunc) {
const handler = {
get (obj, prop) {
if (!filterFunc(prop)) {
let value = Reflect.get(obj, prop);
// auto-bind the methods to the original object, so they will have unrestricted access to it via 'this'.
if (typeof value === 'function') {
value = value.bind(obj);
}
return value;
}
},
set (obj, prop, value) {
if (filterFunc(prop)) {
throw new TypeError(`Can't set property "${prop}"`);
}
return Reflect.set(obj, prop, value);
},
has (obj, prop) {
return filterFunc(prop) ? false : Reflect.has(obj, prop);
},
ownKeys (obj) {
return Reflect.ownKeys(obj).filter(prop => !filterFunc(prop));
},
getOwnPropertyDescriptor (obj, prop) {
return filterFunc(prop) ? undefined : Reflect.getOwnPropertyDescriptor(obj, prop);
}
};
return new Proxy(obj, handler);
}
// trying it out
function propFilter(prop) {
return prop.startsWith('_');
}
const myObj = {
_private: 'secret',
public: 'hello',
method: function () {
console.log(this._private);
}
},
myProxy = privateProps(myObj, propFilter);
console.log(myProxy); // chrome somehow logs the private prop, node doesn't
console.log(JSON.stringify(myProxy)); // {"public":"hello"}
console.log(myProxy._private); // undefined - not accessible from outside
myProxy.method(); // secret - accessible from methods
console.log('_private' in myProxy); // false
console.log(Object.keys(myProxy)); // ["public", "method"]
for (let prop in myProxy) { console.log(prop); } // public, method
try {
myProxy._private = 'chicken attack'; // TypeError: Can't set property "_private"
} catch(ex) {
console.error(ex);
}