ownKeys 拦截器控制遍历操作返回的属性名列表,只影响“哪些键被暴露”,不控制属性存在性或访问权限;必须返回字符串或 Symbol 组成的数组,且须包含所有不可配置自有属性键。
ownkeys 拦截器用于控制 object.getownpropertynames()、object.getownpropertysymbols()、object.keys()、for...in 循环等遍历操作返回的属性名列表。它不决定属性是否存在或能否访问,只决定“哪些键被暴露出来”。
拦截器的基本用法
在 Proxy 的 handler 中定义 ownKeys 方法,它接收目标对象作为参数,必须返回一个数组(且元素必须是字符串或 Symbol):
- 返回的数组决定了所有“可枚举的自有属性键”的集合
- 该数组会影响
Reflect.ownKeys()、Object.keys()、for...in(配合hasOwnProperty判断)等行为 - 即使目标对象实际有某个属性,若未包含在返回数组中,遍历时就“看不见”它
隐藏私有属性(常见场景)
比如约定以 _ 开头的属性为内部使用,可在 ownKeys 中过滤掉:
const target = { name: 'Alice', _id: 123, age: 30 };
const proxy = new Proxy(target, {
ownKeys() {
return Reflect.ownKeys(target).filter(key =>
typeof key === 'string' && !key.startsWith('_')
);
}
});
console.log(Object.keys(proxy)); // ['name', 'age']
for (let k in proxy) console.log(k); // 'name', 'age'
注意:_id 仍可通过 proxy._id 直接读取,ownKeys 不限制访问,只影响“列出键”的行为。
动态控制可见性(基于权限或状态)
可以结合外部条件(如用户角色、调试模式)动态决定返回哪些键:
let showInternal = false;
const data = { user: 'Bob', token: 'abc', createdAt: Date.now() };
const secureProxy = new Proxy(data, {
ownKeys() {
if (showInternal) return Reflect.ownKeys(data);
return Object.keys(data).filter(k => k !== 'token');
}
});
console.log(Object.keys(secureProxy)); // ['user', 'createdAt']
showInternal = true;
console.log(Object.keys(secureProxy)); // ['user', 'token', 'createdAt']
注意事项与限制
- 返回数组必须包含所有不可配置(non-configurable)的自有属性键,否则会抛出
TypeError - 例如:如果
Object.defineProperty(target, 'fixed', { configurable: false }),则ownKeys返回值里必须含'fixed' - 不能凭空添加不存在的键(除非目标对象本身已有对应属性),否则某些方法(如
for...in)可能报错或行为异常 -
ownKeys不影响in操作符或hasOwnProperty—— 它们走的是另一套属性存在性判断逻辑










