【发布时间】:2015-10-12 07:51:59
【问题描述】:
我正在尝试创建一个尽可能隐藏对象私有属性的函数。我在这里将私有属性定义为以下划线开头的属性,例如。 _password.
以下是我目前所得到的(感谢Nicolas Bevacqua's great intro to proxies)。
现在我想知道:
- 我是否使用以下代码覆盖了所有基础?还是我错过了一个重要的代理陷阱,仍然可以通过它访问对象?
- 这是将
Reflect方法与代理结合使用的正确方法吗?我在这里还需要它们吗? - 我为私有财产返回的值是否真实到足以让人们认为该财产真的不存在?
到目前为止我的功能:
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:对于原生浏览器支持,您可能需要在 MS Edge 或 Firefox Dev Edition 中查看。
【问题讨论】:
-
即使你很好地隐藏了属性,这些值不是主要从源脚本或 ajax 响应中可见吗?
-
是的,没错,反正我也无法完全隐藏。我只是不希望他们意外与第三方代码交互(例如,有人循环通过我的代理对象)。
-
Are the values ... real enough你这是什么意思? -
@just-boris 是我为隐藏值返回的值,如果属性不存在,您希望收到这些值?例如。如果属性不存在(不是
undefined、null或其他任何内容),in运算符应返回false。 -
我认为使用代理来隐藏所有私有属性没有任何用处。你不只是从外面隐藏它们,你对每个人都隐藏它们——如果你想编写你的方法来直接访问
target(或o)变量,你可以……呃……*应该* 只是首先使用闭包来保护隐私。
标签: javascript ecmascript-6 es6-proxy