访问对象的不可枚举属性

Iva*_*van 7 javascript prototype object

遵循这个问题:在 Node 中返回Object.prototype空对象

为什么不console.log(Object.prototype)记录预期的对象而是返回{}.

答案是这样的:

这是因为console.log[...] 用于Object.keys()对象,并且它仅返回可枚举属性。并且Object.prototype包含不可枚举的属性,这就是它返回空节点的原因。

——阿姆伦德·辛格


我想知道如何输出给定对象的所有属性(例如Object.prototype)。正如另一个答案所示,使用getOwnPropertyNames效果很好:

const ObjectPrototype = Object.getOwnPropertyNames(Object.prototype).reduce((object, name) => {

  object[name] = Object.prototype[name];

  return object;

}, {});

console.log(
  ObjectPrototype
);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)

我想我可以通过这种方式提取给定对象的隐藏属性。但实际上,它并不能完全发挥作用。

这是一个更简单的例子:我正在检查的对象是 object {mykey: 'value'}。Chrome 给了我它的属性(console.log也是如此),还有它的原型,__proto__灰显:

在此输入图像描述

let object = { mykey: 'value' };

object = Object.getOwnPropertyNames(object).reduce((acc, name) => {

  acc[name] = object[name];

  return acc;

}, {});

console.log(
  object
);
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper { max-height: 100% !important; top: 0; }
Run Code Online (Sandbox Code Playgroud)

上面只返回一个属性。我期待着也有__proto__有没有办法显示一个人的所有属性,包括隐藏的属性?或者我是否必须手动访问它:即减少Object.getOwnPropertyNames(object.__proto__)


PS:或者换句话说,Chrome如何处理隐藏属性?

Pat*_*rts 1

您可以编写一个函数(我们称之为 )getAllPropertyNames(),它迭代对象的原型链并累积每个级别的属性:

function getAllPropertyNames (o) {
  let propertyNames = []

  for (let proto = o; proto !== null; proto = Object.getPrototypeOf(proto)) {
    propertyNames = propertyNames.concat(Object.getOwnPropertyNames(proto))
  }

  return propertyNames
}

console.log(getAllPropertyNames({ mykey: 'value' }))
Run Code Online (Sandbox Code Playgroud)

这些属性不是隐藏的,它们只是继承的,这就是为什么getOwnPropertyNames()不包含它们。它们并不特定于对象,而是特定于从 继承的所有内容Object.prototype

更新

我将尝试一些非常规的东西,但应该产生所需的输出:

// probably could be named better
// feel free to suggest one in comments
function asEnumerable (o) {
  const acc = Object.create(null)

  for (let oProto = o, aProto = acc; oProto !== null; oProto = Object.getPrototypeOf(oProto), aProto = aProto.__proto__) {
    for (const key of Object.getOwnPropertyNames(oProto)) {
      aProto[key] = oProto[key]
    }

    if (Object.getPrototypeOf(oProto) !== null) {
      aProto.__proto__ = Object.create(null)
    }
  }

  return acc
}

console.log(asEnumerable({ mykey: 'value' }))
Run Code Online (Sandbox Code Playgroud)
.as-console-wrapper{min-height:100%!important}
Run Code Online (Sandbox Code Playgroud)

此实现确实遵守规范,因为它不会将__proto__其视为修改对象的继承,而只是将其视为 和 上的普通acc属性aProto