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

Mic*_*ski 10 javascript ecmascript-6 es6-proxy

我有以下代理:

const p = new Proxy({}, {
  ownKeys(target) {
    return ['a', 'b'];
  },
});
Run Code Online (Sandbox Code Playgroud)

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']
Run Code Online (Sandbox Code Playgroud)

Fel*_*ing 17

Object.keys()之间的区别Object.getOwnPropertyNames()Object.keys()[[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']
Run Code Online (Sandbox Code Playgroud)


ade*_*neo 12

Object.keys和之间的区别在于Object.getOwnPropertyNames后者返回自己的属性,无论它们是否可枚举.

添加到对象的属性Proxy是不可枚举的,不会显示在Object.keys,但会显示在Object.getOwnPropertyNames

一般地,通过分配或属性初始化添加的属性默认情况下可枚举的,并且加入的方法,如属性Object.assign,new Proxy等等都是通过默认的非枚举.

MDN上的属性所有权和可枚举性更多,其中人们也可以找到这个表格,概述了两种方法的不同之处

在此输入图像描述

  • 我不知道那张桌子,这很棒! (4认同)