我有以下代理:
const p = new Proxy({}, {
ownKeys(target) {
return ['a', 'b'];
},
});
MDN说:
此陷阱可以拦截这些操作:
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(target) {
return ['a', 'b'];
},
});
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // []
p.c = true;
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // []
p.a = true;
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // ['a']

答案 0 :(得分:16)
Object.keys()
和Object.getOwnPropertyNames()
之间的差异是对象上的Object.keys()
will invoke [[GetOwnProperty]]
,如果返回的属性描述符是可枚举的,则只将属性添加到结果列表。由于对象没有这样的属性,[[GetOwnProperty]]
将返回undefined
,并且属性(名称)将被忽略。
您可以通过实施[[GetOwnProperty]]
:
getOwnPropertyDescriptor
const p = new Proxy({}, {
ownKeys(target) {
return ['a', 'b'];
},
getOwnPropertyDescriptor(k) {
return {
enumerable: true,
configurable: true,
};
}
});
console.log(Object.getOwnPropertyNames(p)); // ['a', 'b']
console.log(Object.keys(p)); // ['a', 'b']

答案 1 :(得分:12)
[x,y] = meshgrid(-2.5 : 0.02:2.5, -2.5 : 0.02: 2.5);
s = x + 1i*y;
z=abs((1+(3/2)*s+sqrt(1+s+(9/4)*s.^2))/2);
figure;
[C,h] = contour(x,y,z,[1 1]);
clabel(C,h)
hold on
z=abs((1+(3/2)*s-sqrt(1+s+(9/4)*s.^2))/2);
[C,h] = contour(x,y,z,[1 1]);
clabel(C,h)
和Object.keys
之间的区别在于后者返回自己的属性,无论它们是否可枚举。
Object.getOwnPropertyNames
添加到对象的属性不可枚举,并且不会显示在Proxy
中,但会显示在Object.keys
通常,默认情况下,通过赋值或属性初始值设定项添加的属性是可枚举的,并且使用Object.getOwnPropertyNames
,Object.assign
等方法添加的属性在默认情况下是不可枚举的。
MDN还有关于财产所有权和可枚举性的更多信息,其中一个人也可以找到这个概述两种方法差异的表格