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

时间:2016-11-01 00:43:19

标签: javascript ecmascript-6 es6-proxy

我有以下代理:

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']




2 个答案:

答案 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.getOwnPropertyNamesObject.assign等方法添加的属性在默认情况下是不可枚举的。

MDN还有关于财产所有权和可枚举性的更多信息,其中一个人也可以找到这个概述两种方法差异的表格

enter image description here