Javascript 为什么在使用ownKeys处理程序调用代理对象时,Object.keys()和Object.getOwnPropertyNames()会产生不同的输出?

Javascript 为什么在使用ownKeys处理程序调用代理对象时,Object.keys()和Object.getOwnPropertyNames()会产生不同的输出?,javascript,ecmascript-6,es6-proxy,Javascript,Ecmascript 6,Es6 Proxy,我有以下代理人: const p = new Proxy({}, { ownKeys(target) { return ['a', 'b']; }, }); 他说: 此陷阱可以拦截以下操作: Object.getOwnPropertyNames() Object.getOwnPropertySymbols() Object.keys() Reflect.ownKeys() 因此,我期望Object.getOwnPropertyNames()和Object.keys()产生相

我有以下代理人:

const p = new Proxy({}, {
  ownKeys(target) {
    return ['a', 'b'];
  },
});
他说:

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

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • Reflect.ownKeys()
因此,我期望
Object.getOwnPropertyNames()
Object.keys()
产生相同的输出。但是,
Object.getOwnPropertyNames(p)
返回
['a',b']
(如预期的那样),但是
Object.keys(p)
返回一个空数组。为什么呢

此外,如果我向该对象添加了一个属性,而该属性不是由
ownKeys
处理程序返回的(例如
c
),则两个函数都会忽略它(它们不会更改输出)。但是,当我添加由
ownKeys
处理程序返回的属性(例如
a
)时,
Object.keys(p)
现在返回
['a']

代码段:

const p=new Proxy({}{
ownKeys(目标){
返回['a','b'];
},
});
console.log(Object.getOwnPropertyNames(p));//['a','b']
console.log(Object.keys(p));//[]
p、 c=正确;
console.log(Object.getOwnPropertyNames(p));//['a','b']
console.log(Object.keys(p));//[]
p、 a=真;
console.log(Object.getOwnPropertyNames(p));//['a','b']

console.log(Object.keys(p));//['a']
Object.keys和
Object.getOwnPropertyNames
之间的区别在于后者返回自己的属性,而不管它们是否可枚举

通过
代理添加到对象中的属性是不可枚举的,不会显示在
对象.key
中,但会显示在
对象.getOwnPropertyNames

通常,默认情况下,通过赋值或属性初始值设定项添加的属性是可枚举的,而通过
Object.assign
new Proxy
等方法添加的属性是不可枚举的

这里有更多关于属性所有权和可枚举性的内容,您也可以在这张表中找到这两种方法的区别

和之间的区别在于对象上的区别,并且仅当返回的属性描述符可枚举时才将属性添加到结果列表中。由于对象没有这样的属性,
[[GetOwnProperty]]
将返回
未定义的
,并且忽略该属性(名称)

通过实现
getOwnPropertyDescriptor
,可以覆盖/实现代理中的
[[GetOwnProperty]]

const p=new Proxy({}{
ownKeys(目标){
返回['a','b'];
},
getOwnPropertyDescriptor(k){
返回{
可枚举:正确,
对,,
};
}
});
console.log(Object.getOwnPropertyNames(p));//['a','b']

console.log(Object.keys(p));//['a','b']
At
javascript
At Answer值仅由处理程序返回,而不是在
target
对象上设置,是吗?在
target
对象
{}
上似乎没有设置实际属性;虽然
{}
Proxy()
调用之外没有标识符,但可以使用函数的参数引用目标对象。数组或对象仅由函数
返回
,而不是设置在
目标
{}
?@FelixKling因此,按照您的思路,如果使用
对象定义了a和b,则应该能够列出它们。defneProperty
并将其设置为可枚举,对吗?我试过了,但没有成功。知道为什么吗?我不知道那张桌子,太棒了!