I'm trying to create a function that hides private properties on Objects as well as possible. I would define private properties here as those that begin with an underscore, eg. _password
.
Below is what I've got so far (thanks to Nicolas Bevacqua's great intro to proxies).
Now I was wondering:
- Am I covering all bases with the following code? Or am I missing an important proxy trap through which the objects could still be accessed?
- Is this the right way to use the
Reflect
methods in conjunction with a proxy? And do I even need them here? - Are the values I return for private properties real enough to let people think that the property really does not exist?
My function so far:
function privatize(obj, prefix = '_', throwError = false) {
const proxyHandler = {
get(target, key) {
return private(key, 'get') ? undefined : Reflect.get(target, key);
},
set(target, key, value) {
return private(key, 'set') ? undefined : Reflect.set(target, key, value);
},
has(target, key) {
return private(key, 'has') ? false : Reflect.has(target, key);
},
deleteProperty(target, key) {
return private(key, 'delete') ? false : Reflect.deleteProperty(target, key);
},
defineProperty(target, key, descriptor) {
return private(key, 'defineProperty') ? false : Reflect.defineProperty(target, key, descriptor);
},
enumerate(target) {
return Object.keys().filter((key) => {
return !private(key, null, false);
})[Symbol.iterator]();
},
ownKeys(target) {
return Reflect.ownKeys(target).filter((key) => {
return !private(key, null, false);
});
},
getOwnPropertyDescriptor(target, key) {
return private(key, 'getOwnPropertyDescriptor') ? false : Reflect.getOwnPropertyDescriptor(target, key);
}
};
function private(key, operationName) {
if (key.indexOf(prefix) === 0) {
if (throwError) {
throw new Error(`Operation '${operationName}' is not allowed on private properties.`);
}
return true;
}
}
return new Proxy(obj, proxyHandler);
}
var o = {
first: 'should work',
_second: 'should fail'
};
var proxied = privatize(o);
console.log(proxied);
PS: For native browser support, you might have to look at it in MS Edge or Firefox Dev Edition.