为什么 ownKeys 代理陷阱不能与 Object.keys() 一起使用?

sdg*_*uck 8 javascript ecmascript-6 es6-proxy

在MDN 上的代理陷阱文档ownKeys中,它指出它将拦截Object.keys()调用:

该陷阱可以拦截以下操作:

Object.getOwnPropertyNames()

Object.getOwnPropertySymbols()

对象.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))
Run Code Online (Sandbox Code Playgroud)

Anu*_*rag 7

原因很简单:Object.keys仅返回带有可枚举标志的属性。为了检查它,它调用[[GetOwnProperty]]每个属性的内部方法来获取其描述符。而这里,由于\xe2\x80\x99s没有属性,它的描述符为空,没有可枚举标志,所以它\xe2\x80\x99s被跳过。

\n

为了Object.keys返回一个属性,我们需要它存在于对象中,并带有可枚举标志,或者我们可以拦截对 [[GetOwnProperty]] 的调用(陷阱 getOwnPropertyDescriptor 可以做到这一点),并返回一个带有 enumerable: true 的描述符。

\n

这里\xe2\x80\x99s 是一个例子:

\n

\r\n
\r\n
let user = { };\n\nuser = new Proxy(user, {\n  ownKeys(target) { // called once to get a list of properties\n    return [\'a\', \'b\', \'c\'];\n  },\n\n  getOwnPropertyDescriptor(target, prop) { // called for every property\n    return {\n      enumerable: true,\n      configurable: true\n      /* ...other flags, probable "value:..." */\n    };\n  }\n\n});\n\nconsole.log( Object.keys(user) ); // [\'a\', \'b\', \'c\']
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n

来源

\n