为什么 ownKeys 代理陷阱不能与 Object.keys() 一起使用?
Why isn't ownKeys Proxy trap working with Object.keys()?
在 documentation of the Proxy ownKeys
trap on MDN 中声明它将拦截 Object.keys()
调用:
This trap can intercept these operations:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
但是,根据我的测试,它似乎不适用于 Object.keys
:
const proxy = new Proxy({}, {
ownKeys() {
console.log("called")
return ["a", "b", "c"]
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))
是MDN错了,还是我做错了什么?
原因很简单:Object.keys
returns 只有带有可枚举标志的属性。为了检查它,它为每个 属性 调用内部方法 [[GetOwnProperty]]
以获取其描述符。而这里,由于没有属性,它的描述符是空的,没有可枚举标志,所以跳过。
对于Object.keys
到return一个属性,我们需要它存在于对象中,带有可枚举标志,或者我们可以拦截对[[GetOwnProperty]]的调用(陷阱 getOwnPropertyDescriptor 做到了),以及 return 一个带有 enumerable: true 的描述符。
这是一个例子:
let user = { };
user = new Proxy(user, {
ownKeys(target) { // called once to get a list of properties
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, prop) { // called for every property
return {
enumerable: true,
configurable: true
/* ...other flags, probable "value:..." */
};
}
});
console.log( Object.keys(user) ); // ['a', 'b', 'c']
Object.keys
returns 只有对象的 enumerable 自有属性。您的代理没有这样的,或者至少它没有在其 getOwnPropertyDescriptor
陷阱中报告它们。它适用于
const proxy = new Proxy({}, {
ownKeys() {
console.log("called ownKeys")
return ["a", "b", "c"]
},
getOwnPropertyDescriptor(target, prop) {
console.log(`called getOwnPropertyDescriptor(${prop})`);
return { configurable: true, enumerable: true };
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))
在 documentation of the Proxy ownKeys
trap on MDN 中声明它将拦截 Object.keys()
调用:
This trap can intercept these operations:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
Reflect.ownKeys()
但是,根据我的测试,它似乎不适用于 Object.keys
:
const proxy = new Proxy({}, {
ownKeys() {
console.log("called")
return ["a", "b", "c"]
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))
是MDN错了,还是我做错了什么?
原因很简单:Object.keys
returns 只有带有可枚举标志的属性。为了检查它,它为每个 属性 调用内部方法 [[GetOwnProperty]]
以获取其描述符。而这里,由于没有属性,它的描述符是空的,没有可枚举标志,所以跳过。
对于Object.keys
到return一个属性,我们需要它存在于对象中,带有可枚举标志,或者我们可以拦截对[[GetOwnProperty]]的调用(陷阱 getOwnPropertyDescriptor 做到了),以及 return 一个带有 enumerable: true 的描述符。
这是一个例子:
let user = { };
user = new Proxy(user, {
ownKeys(target) { // called once to get a list of properties
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, prop) { // called for every property
return {
enumerable: true,
configurable: true
/* ...other flags, probable "value:..." */
};
}
});
console.log( Object.keys(user) ); // ['a', 'b', 'c']
Object.keys
returns 只有对象的 enumerable 自有属性。您的代理没有这样的,或者至少它没有在其 getOwnPropertyDescriptor
陷阱中报告它们。它适用于
const proxy = new Proxy({}, {
ownKeys() {
console.log("called ownKeys")
return ["a", "b", "c"]
},
getOwnPropertyDescriptor(target, prop) {
console.log(`called getOwnPropertyDescriptor(${prop})`);
return { configurable: true, enumerable: true };
}
})
console.log(Object.keys(proxy))
console.log(Object.getOwnPropertyNames(proxy))
console.log(Reflect.ownKeys(proxy))