recursal/MDN huggingface dataset:
Object.getOwnPropertySymbols()
==============================

**`Object.getOwnPropertySymbols()`** 静态方法返回一个包含给定对象所有自有 Symbol 属性的数组。

尝试一下
----

语法
--


```js
Object.getOwnPropertySymbols(obj)
```

### 参数

`obj`

要返回 Symbol 属性的对象。

### 返回值

在给定对象找到的所有自有 Symbol 属性的数组。

描述
--

与 `Object.getOwnPropertyNames()` 类似，你可以将给定对象的所有符号属性作为 Symbol 数组获取。请注意，`Object.getOwnPropertyNames()` 本身不包含对象的 Symbol 属性，只包含字符串属性。

因为所有的对象在初始化的时候不会包含任何自有的 Symbol 属性，除非你在对象上分配了 Symbol 属性，否则 `Object.getOwnPropertySymbols()` 只会返回一个空的数组。

示例
--

### 使用 Object.getOwnPropertySymbols()


```js
const obj = {};
const a = Symbol("a");
const b = Symbol.for("b");

obj[a] = "localSymbol";
obj[b] = "globalSymbol";

const objectSymbols = Object.getOwnPropertySymbols(obj);

console.log(objectSymbols.length); // 2
console.log(objectSymbols); // [Symbol(a), Symbol(b)]
console.log(objectSymbols[0]); // Symbol(a)
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.getownpropertysymbols |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.getOwnPropertySymbols` 的 polyfill
* `Object.getOwnPropertyNames()`
* `Symbol`
Object.prototype.propertyIsEnumerable()
=======================================

**`propertyIsEnumerable()`** 方法返回一个布尔值，表示指定的属性是否是对象的可枚举自有属性。

尝试一下
----

语法
--


```js
propertyIsEnumerable(prop)
```

### 参数

`prop`

需要测试的属性名，可以是字符串或 `Symbol`。

### 返回值

一个布尔值，指示指定的属性是否可枚举并且是对象自有的属性。

描述
--

所有继承自 `Object.prototype`（即除了 `null` 原型对象之外的所有对象）都继承了 `propertyIsEnumerable()` 方法。该方法判断指定的属性（字符串或 symbol 值）是否是对象的可枚举自有属性。如果对象没有指定的属性，则该方法返回 `false`。

此方法等价于 `Object.getOwnPropertyDescriptor(obj, prop)?.enumerable ?? false`。

示例
--

### 使用 propertyIsEnumerable()

以下示例演示了在对象和数组上使用 `propertyIsEnumerable()`。


```js
const o = {};
const a = [];
o.prop = "是可枚举的";
a[0] = "是可枚举的";

o.propertyIsEnumerable("prop"); // true
a.propertyIsEnumerable(0); // true
```

### 用户自定义对象和内置对象

大多数内置属性默认情况下是不可枚举的，而用户创建的对象属性通常是可枚举的，除非明确指定为不可枚举。


```js
const a = ["是可枚举的"];

a.propertyIsEnumerable(0); // true
a.propertyIsEnumerable("length"); // false

Math.propertyIsEnumerable("random"); // false
globalThis.propertyIsEnumerable("Math"); // false
```

### 自有属性和继承属性

只有可枚举自有属性会令 `propertyIsEnumerable()` 返回 `true`，尽管 `for...in` 循环会访问所有可枚举属性，包括继承的属性。


```js
const o1 = {
  enumerableInherited: "是可枚举的",
};
Object.defineProperty(o1, "nonEnumerableInherited", {
  value: "是不可枚举的",
  enumerable: false,
});
const o2 = {
  // o1 是 o2 的原型
  \_\_proto\_\_: o1,
  enumerableOwn: "是可枚举的",
};
Object.defineProperty(o2, "nonEnumerableOwn", {
  value: "是不可枚举的",
  enumerable: false,
});

o2.propertyIsEnumerable("enumerableInherited"); // false
o2.propertyIsEnumerable("nonEnumerableInherited"); // false
o2.propertyIsEnumerable("enumerableOwn"); // true
o2.propertyIsEnumerable("nonEnumerableOwn"); // false
```

### 测试 Symbol 属性

`propertyIsEnumerable()` 也支持 `Symbol` 属性。请注意，大多数枚举方法只访问字符串属性；当使用 `Object.assign()` 或展开语法时，symbol 属性的可枚举性才有用。更多信息，请参见属性的枚举性和所有权。


```js
const sym = Symbol("可枚举的");
const sym2 = Symbol("不可枚举的");
const o = {
  [sym]: "是可枚举的",
};
Object.defineProperty(o, sym2, {
  value: "是不可枚举的",
  enumerable: false,
});

o.propertyIsEnumerable(sym); // true
o.propertyIsEnumerable(sym2); // false
```

### 在 null 原型对象上使用

由于 `null` 原型对象不从 `Object.prototype` 继承，它们不会继承 `propertyIsEnumerable()` 方法。你必须使用该对象作为 `this` 来调用 `Object.prototype.propertyIsEnumerable`。


```js
const o = {
  \_\_proto\_\_: null,
  enumerableOwn: "是可枚举的",
};

o.propertyIsEnumerable("enumerableOwn"); // TypeError: o.propertyIsEnumerable is not a function
Object.prototype.propertyIsEnumerable.call(o, "enumerableOwn"); // true
```


或者，你也可以使用 `Object.getOwnPropertyDescriptor()`，它也有助于区分不存在的属性和实际上不可枚举的属性。


```js
const o = {
  \_\_proto\_\_: null,
  enumerableOwn: "是可枚举的",
};

Object.getOwnPropertyDescriptor(o, "enumerableOwn")?.enumerable; // true
Object.getOwnPropertyDescriptor(o, "nonExistent")?.enumerable; // undefined
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.prototype.propertyisenumerable |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* 属性的可枚举性和所有权
* `for...in`
* `Object.keys()`
* `Object.defineProperty()`
Object.keys()
=============

**`Object.keys()`** 静态方法返回一个由给定对象自身的可枚举的字符串键属性名组成的数组。

尝试一下
----

语法
--


```js
Object.keys(obj)
```

### 参数

`obj`

一个对象。

### 返回值

一个由给定对象自身可枚举的字符串键属性键组成的数组。

描述
--

`Object.keys()` 返回一个数组，其元素是字符串，对应于直接在对象上找到的可枚举的字符串键属性名。这与使用 `for...in` 循环迭代相同，只是 `for...in` 循环还会枚举原型链中的属性。`Object.keys()` 返回的数组顺序和与 `for...in` 循环提供的顺序相同。

如果你需要属性的值，请使用 `Object.values()`。如果你同时需要属性的键和值，请使用 `Object.entries()`。

示例
--

### 使用 Object.keys()


```js
// 简单数组
const arr = ["a", "b", "c"];
console.log(Object.keys(arr)); // ['0', '1', '2']

// 类数组对象
const obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.keys(obj)); // ['0', '1', '2']

// 键的顺序随机的类数组对象
const anObj = { 100: "a", 2: "b", 7: "c" };
console.log(Object.keys(anObj)); // ['2', '7', '100']

// getFoo 是一个不可枚举的属性
const myObj = Object.create(
  {},
  {
    getFoo: {
      value() {
        return this.foo;
      },
    },
  },
);
myObj.foo = 1;
console.log(Object.keys(myObj)); // ['foo']
```


如果你想要*所有*以字符串为键的自有属性，包括不可枚举的属性，参见 `Object.getOwnPropertyNames()`。

### 在基本类型中使用 Object.keys()

非对象参数会强制转换为对象。`undefined` 和 `null` 不能被强制转换为对象，会立即抛出 `TypeError`。只有字符串可以有自己的可枚举属性，而其他所有基本类型都返回一个空数组。


```js
// 字符串具有索引作为可枚举的自有属性
console.log(Object.keys("foo")); // ['0', '1', '2']

// 其他基本类型（除了 undefined 和 null）没有自有属性
console.log(Object.keys(100)); // []
```


**备注：** 在 ES5 中，将一个非对象传递给 `Object.keys()` 会抛出一个 `TypeError`。

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.keys |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.keys` 的 Polyfill
* 属性的可枚举性和所有权
* `Object.entries()`
* `Object.values()`
* `Object.prototype.propertyIsEnumerable()`
* `Object.create()`
* `Object.getOwnPropertyNames()`
* `Map.prototype.keys()`
Object.prototype.\_\_defineGetter\_\_()
=======================================

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

**备注：** 此特性已弃用，建议使用对象初始化语法或 `Object.defineProperty()` API 来定义 getter。该方法的行为只针对 Web 兼容性进行了规定，在任何平台上都不需要实现该方法。它可能无法在所有地方正常工作。

**`__defineGetter__()`** 方法将一个对象的属性绑定到一个函数上，当该属性被访问时，该函数将被调用。

语法
--


```js
\_\_defineGetter\_\_(prop, func)
```

### 参数

`prop`

`func` 所绑定的 getter 函数所对应的属性名称，以字符串形式表示。

`func`

绑定到指定属性查询的函数。

### 返回值

`undefined`。

### 异常

`TypeError`

如果 `func` 不是函数，则抛出。

描述
--

所有继承自 `Object.prototype` 的对象（也就是除了 `null` 原型对象的对象）都会继承 `__defineGetter__()` 方法。该方法允许在一个已存在的对象上定义一个 getter。这相当于使用 `Object.defineProperty(obj, prop, { get: func, configurable: true, enumerable: true })` 方法，这意味着该属性是可枚举和可配置的，而且如果存在，则保留任何现有的 setter。

`__defineGetter__()` 在规范中被定义为“可选规范”，这意味着不需要任何实现来实现它。然而，所有主要的浏览器都实现了它，并且由于它的持续使用，它不太可能被删除。如果一个浏览器实现了 `__defineGetter__()`，那么它还需要实现 `__lookupGetter__()`、`__lookupSetter__()` 和 `__defineSetter__()` 方法。

示例
--

### 使用 \_\_defineGetter\_\_()


```js
const o = {};
o.\_\_defineGetter\_\_("gimmeFive", function () {
  return 5;
});
console.log(o.gimmeFive); // 5
```

### 以标准方式定义 getter 属性

在对象首次初始化时，你可以使用 `get` 语法来定义一个 getter。


```js
const o = {
  get gimmeFive() {
    return 5;
  },
};
console.log(o.gimmeFive); // 5
```


你也可以使用 `Object.defineProperty()` 在对象创建后为其定义一个 getter。与 `__defineGetter__()` 相比，此方法允许你控制 getter 的可枚举性和可配置性，以及定义 Symbol 属性。`Object.defineProperty()` 方法也适用于 `null` 原型对象，因为他们没有继承 `Object.prototype`，所以没有 `__defineGetter__()` 方法。


```js
const o = {};
Object.defineProperty(o, "gimmeFive", {
  get() {
    return 5;
  },
  configurable: true,
  enumerable: true,
});
console.log(o.gimmeFive); // 5
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.prototype.\_\_defineGetter\_\_ |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.prototype.__defineGetter__` 的 polyfill
* `Object.prototype.__defineSetter__()`
* `get` 语法
* `Object.defineProperty()`
* `Object.prototype.__lookupGetter__()`
* `Object.prototype.__lookupSetter__()`
* JS 指南：定义 Getter 和 Setter
* [博文] \_\_defineGetter\_\_ 和 \_\_defineSetter\_\_ 已被弃用
* Firefox bug 647423
Object.defineProperties()
=========================

**`Object.defineProperties()`** 静态方法直接在一个对象上定义新的属性或修改现有属性，并返回该对象。

尝试一下
----

语法
--


```js
Object.defineProperties(obj, props)
```

### 参数

`obj`

在其上定义或修改属性的对象。

`props`

一个对象，其中每个键表示要定义或修改的属性的名称，每个值是描述该属性的对象。在 `props` 中的每个值必须是且只能是数据描述符或访问器描述符之一；不能同时为两者（更多详细信息，请参见`Object.defineProperty()`）。

数据描述符和访问器描述符可以包含以下可选键：

`configurable`

如果此属性描述符的类型可以更改并且属性可以从相应的对象中删除，则为 `true`。**默认为 `false`。**

`enumerable`

如果此属性在枚举相应对象的属性时应显示出来，则为 `true`。**默认为 `false`。**

数据描述符还具有以下可选键：

`value`

与属性关联的值。可以是任何有效的 JavaScript 值（数字、对象、函数等）。**默认为 `undefined`。**

`writable`

如果与属性关联的值可以使用赋值运算符更改，则为 `true`。**默认为 `false`。**

访问器描述符还具有以下可选键：

`get`

作为该属性的 getter 函数，如果没有 getter 则为 `undefined`。函数返回值将被用作属性的值。**默认为 `undefined`。**

`set`

作为该属性的 setter 函数，如果没有 setter 则为 `undefined`。该函数将只接收一个参数，即被分配给属性的新值。**默认为 `undefined`。**

如果一个属性描述符没有 `value`、`writable`、`get`、`set` 键中的任何一个，那么它被视为一个数据描述符。如果一个属性描述符同时具有 `value` 或 `writable` 和 `get` 或 `set` 键中的任意一个组合，就会抛出异常。

### 返回值

传递给函数的对象。

示例
--

### 使用 Object.defineProperties


```js
const obj = {};
Object.defineProperties(obj, {
  property1: {
    value: true,
    writable: true,
  },
  property2: {
    value: "Hello",
    writable: false,
  },
  // 等等……
});
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.defineproperties |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.defineProperties` 的 polyfill
* `Object.defineProperty()`
* `Object.keys()`
* 属性的可枚举性和所有权
Object.preventExtensions()
==========================

**`Object.preventExtensions()`** 静态方法可以防止新属性被添加到对象中（即防止该对象被扩展）。它还可以防止对象的原型被重新指定。

尝试一下
----

语法
--


```js
Object.preventExtensions(obj)
```

### 参数

`obj`

将要变得不可扩展的对象。

### 返回值

已经不可扩展的对象。

描述
--

如果一个对象可以添加新的属性，则这个对象是可扩展的。`Object.preventExtensions()` 将对象标记为不再可扩展，这样它将永远不会具有它被标记为不可扩展时持有的属性之外的属性。注意，一般来说，不可扩展对象的属性仍然可以被*删除*。尝试向不可扩展对象添加新属性将静默失败，或在严格模式中抛出 `TypeError`。

与 `Object.seal()` 和 `Object.freeze()` 不同，`Object.preventExtensions()` 调用了内在的 JavaScript 行为，不能用几个其他操作的组合替代。它还有它的 `Reflect` 对应方法（仅存在于内部操作中），`Reflect.preventExtensions()`。

`Object.preventExtensions()` 只能防止添加自有属性。但其对象类型的原型依然可以添加新的属性。

该方法使得目标对象的 `[[Prototype]]` 不可变；任何重新赋值 `[[Prototype]]` 操作都会抛出 `TypeError` 。这种行为只针对内部的 `[[Prototype]]` 属性，目标对象的其他属性将保持可变。

一旦将对象变为不可扩展的对象，就再也不能使其可扩展。

示例
--

### 使用 Object.preventExtensions()


```js
// Object.preventExtensions 将原对象变的不可扩展，并且返回原对象。
const obj = {};
const obj2 = Object.preventExtensions(obj);
obj === obj2; // true

// 字面量方式定义的对象默认是可扩展的。
const empty = {};
Object.isExtensible(empty); // true

// 可以将其改变为不可扩展的。
Object.preventExtensions(empty);
Object.isExtensible(empty); // false

// 使用 Object.defineProperty 方法为一个不可扩展的对象添加新属性会抛出异常。
const nonExtensible = { removable: true };
Object.preventExtensions(nonExtensible);
Object.defineProperty(nonExtensible, "new", {
  value: 8675309,
}); // 抛出 TypeError

// 在严格模式中，为一个不可扩展对象的新属性赋值会抛出 TypeError 异常。
function fail() {
  "use strict";
  // 抛出 TypeError
  nonExtensible.newProperty = "FAIL";
}
fail();
```


不可扩展对象的原型是不可变的：


```js
const fixed = Object.preventExtensions({});
// 抛出 TypeError
fixed.__proto__ = { oh: "hai" };
```

非对象参数
-----

在 ES5 中，如果提供给该方法的参数不是一个对象类型（而是原始类型），将抛出 `TypeError`。在 ES2015 中，非对象参数将被原样返回，因为原始类型是定义上不可变的。


```js
Object.preventExtensions(1);
// TypeError: 1 is not an object (ES5 code)

Object.preventExtensions(1);
// 1 (ES2015 code)
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.preventextensions |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Object.isExtensible()`
* `Object.seal()`
* `Object.isSealed()`
* `Object.freeze()`
* `Object.isFrozen()`
* `Reflect.preventExtensions()`
Object.prototype.valueOf()
==========================

`Object` 实例的 **`valueOf()`** 方法将 `this` 值转换成对象。该方法旨在被派生对象重写，以实现自定义类型转换逻辑。

尝试一下
----

语法
--


```js
valueOf()
```

### 参数

无。

### 返回值

转换成对象的 `this` 值。

**备注：** 为了使 `valueOf` 在类型转换过程中有用，它必须返回一个基本类型值。因为所有的基本类型都有自己的 `valueOf()` 方法，所以调用 `aPrimitiveValue.valueOf()` 通常不会调用 `Object.prototype.valueOf()`。

描述
--

JavaScript 调用 `valueOf` 方法来将对象转换成基本类型值。你很少需要自己调用 `valueOf` 方法；当遇到需要基本类型值的对象时，JavaScript 会自动的调用该方法。

强制数字类型转换和强制基本类型转换优先会调用该方法，而强制字符串转换会优先调用 `toString()`，并且 `toString()` 很可能返回字符串值（甚至对于 `Object.prototype.toString()` 基本实现也是如此），因此在这种情况下不会调用 `valueOf()`。

从 `Object.prototype` 继承的所有对象（即，除了`null` 原型对象之外的所有对象）都继承了 `toString()` 方法。`Object.prototype.valueOf()` 的基本实现被有意设计为无用的：返回一个对象；其返回值将永远不会被任何基本类型转换算法使用。许多内置对象重写此方法以返回适当的基本类型值。创建自定义对象时，可以重写 `valueOf()` 来调用自定义方法，以便将自定义对象转换为基本类型值。通常，`valueOf()` 用于返回对对象具有意义的值——与 `toString()` 不同，它不需要字符串。或者，你可以添加一个 `@@toPrimitive` 方法，该方法允许对转换过程进行更多控制，并且对于任何类型的转换，始终优先于 `valueOf` 或 `toString`。

示例
--

### 使用 valueOf()

基本的 `valueOf()` 方法返回 `this` 值本身，如果尚未转换为对象，则转换成对象。因此，任何基本类型转换算法都不会使用它的返回值。


```js
const obj = { foo: 1 };
console.log(obj.valueOf() === obj); // true

console.log(Object.prototype.valueOf.call("primitive"));
// [String: 'primitive']（一个包装对象）
```

### 重写自定义对象的 valueOf

你可以创建一个要调用的函数来代替默认的 `valueOf` 方法。你的函数不应该接受任何参数，因为在类型转换期间调用它时不会传递任何参数。

例如，你可以将 `valueOf` 方法添加到自定义类 `Box` 中。


```js
class Box {
  #value;
  constructor(value) {
    this.#value = value;
  }
  valueOf() {
    return this.#value;
  }
}
```


有了前面的代码，任何时候在将 `Box` 类型的对象表示为基本类型值（但不是特定的字符串）的上下文中使用时，JavaScript 都会自动调用前面代码中定义的函数。


```js
const box = new Box(123);
console.log(box + 456); // 579
console.log(box == 123); // true
```


对象的 `valueOf` 方法通常由 JavaScript 调用，但你可以按照如下方式自己调用它：


```js
box.valueOf();
```

### 对对象使用一元加运算符

一元加（+）对其操作数进行强制数字转换，对于大多数没有 `@@toPrimitive` 的对象，这意味着调用其 `valueOf()`。但是，如果对象没有自定义的 `valueOf()` 方法，则基本实现将导致忽略 `valueOf()`，而使用 `toString()` 的返回值。


```js
+new Date(); // 当前时间戳；与 new Date().getTime() 相同
+{}; // NaN（toString() 返回 "[object Object]"）
+[]; // 0（toString() 返回一个空的字符串列表）
+[1]; // 1（toString() 返回 "1"）
+[1, 2]; // NaN（toString() 返回 "1,2"）
+new Set([1]); // NaN（toString() 返回 "[object Set]"）
+{ valueOf: () => 42 }; // 42
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.prototype.valueof |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `Object.prototype.toString()`
* `parseInt()`
* `Symbol.toPrimitive`
Object.getOwnPropertyNames()
============================

**`Object.getOwnPropertyNames()`** 静态方法返回一个数组，其包含给定对象中所有自有属性（包括不可枚举属性，但不包括使用 symbol 值作为名称的属性）。

尝试一下
----

语法
--


```js
Object.getOwnPropertyNames(obj)
```

### 参数

`obj`

一个对象，其自有的可枚举和不可枚举属性的名称被返回。

### 返回值

在给定对象上找到的自有属性对应的字符串数组。

描述
--

`Object.getOwnPropertyNames()` 返回一个数组，其元素是与给定对象 `obj` 直接关联的可枚举和不可枚举属性对应的字符串。数组中可枚举属性的顺序与使用 `for...in` 循环（或 `Object.keys()`）遍历对象属性时所暴露的顺序一致。对象的非负整数键（包括可枚举和不可枚举的）首先按升序添加到数组中，然后是按插入顺序排列的字符串键。

在 ES5 中，如果该方法的参数不是一个对象（而是基本类型值），则会导致 `TypeError`。在 ES2015 中，非对象参数会被强制转换为对象。


```js
Object.getOwnPropertyNames("foo");
// TypeError: "foo" is not an object (ES5 code)

Object.getOwnPropertyNames("foo");
// ["0", "1", "2", "length"] (ES2015 code)
```

示例
--

### 使用 Object.getOwnPropertyNames()


```js
const arr = ["a", "b", "c"];
console.log(Object.getOwnPropertyNames(arr).sort());
// ["0", "1", "2", "length"]

// 类数组对象
const obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.getOwnPropertyNames(obj).sort());
// ["0", "1", "2"]

Object.getOwnPropertyNames(obj).forEach((val, idx, array) => {
  console.log(`${val} -> ${obj[val]}`);
});
// 0 -> a
// 1 -> b
// 2 -> c

// 不可枚举属性
const myObj = Object.create(
  {},
  {
    getFoo: {
      value() {
        return this.foo;
      },
      enumerable: false,
    },
  },
);
myObj.foo = 1;

console.log(Object.getOwnPropertyNames(myObj).sort()); // ["foo", "getFoo"]
```


如果你只想获取可枚举属性，请参见 `Object.keys()` 或使用 `for...in` 循环（请注意，这也将返回对象原型链中找到的可枚举属性，除非使用 `hasOwn()` 过滤）。

原型链上的属性不会被列出：


```js
function ParentClass() {}
ParentClass.prototype.inheritedMethod = function () {};

function ChildClass() {
  this.prop = 5;
  this.method = function () {};
}
ChildClass.prototype = new ParentClass();
ChildClass.prototype.prototypeMethod = function () {};

console.log(Object.getOwnPropertyNames(new ChildClass()));
// ["prop", "method"]
```

### 只获取不可枚举的属性

这个方法使用 `Array.prototype.filter()` 函数从所有键（使用 `Object.getOwnPropertyNames()` 获得）的列表中过滤可枚举键（使用 `Object.keys()` 获得），从而仅以不可枚举键作为输出。


```js
const target = myObject;
const enumAndNonenum = Object.getOwnPropertyNames(target);
const enumOnly = new Set(Object.keys(target));
const nonenumOnly = enumAndNonenum.filter((key) => !enumOnly.has(key));

console.log(nonenumOnly);
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.getownpropertynames |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.getOwnPropertyNames` 的 polyfill
* 属性的可枚举性和所有权
* `Object.hasOwn()`
* `Object.prototype.propertyIsEnumerable()`
* `Object.create()`
* `Object.keys()`
* `Array.prototype.forEach()`
Object.getPrototypeOf()
=======================

**`Object.getPrototypeOf()`** 静态方法返回指定对象的原型（即内部 `[[Prototype]]` 属性的值）。

尝试一下
----

语法
--


```js
Object.getPrototypeOf(obj)
```

### 参数

`obj`

要返回其原型的对象。

### 返回值

给定对象的原型，可能是 `null`。

示例
--

### 使用 getPrototypeOf


```js
const proto = {};
const obj = Object.create(proto);
Object.getPrototypeOf(obj) === proto; // true
```

### 非对象强制类型转换

在 ES5 中，如果 `obj` 参数不是对象，则会抛出 `TypeError` 异常。在 ES2015 中，该参数将被强制转换为 `Object`。


```js
Object.getPrototypeOf("foo");
// TypeError: "foo" is not an object (ES5 code)
Object.getPrototypeOf("foo");
// String.prototype (ES2015 code)
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.getprototypeof |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.getPrototypeOf` 的 polyfill
* `Object.prototype.isPrototypeOf()`
* `Object.setPrototypeOf()`
* `Object.prototype.__proto__`
* John Resig 关于 getPrototypeOf 的博文。
* `Reflect.getPrototypeOf()`
Object.prototype.\_\_lookupGetter\_\_()
=======================================

**已弃用:** 不再推荐使用该特性。虽然一些浏览器仍然支持它，但也许已从相关的 web 标准中移除，也许正准备移除或出于兼容性而保留。请尽量不要使用该特性，并更新现有的代码；参见本页面底部的兼容性表格以指导你作出决定。请注意，该特性随时可能无法正常工作。

**备注：** 该特性已被弃用，建议使用 `Object.getOwnPropertyDescriptor()` API。该方法的行为只针对 Web 兼容性进行了规定，在任何平台上都不需要实现该方法。它可能无法在所有地方正常工作。

**`__lookupGetter__()`** 方法返回绑定到指定属性的 getter 函数。

语法
--


```js
\_\_lookupGetter\_\_(prop)
```

### 参数

`prop`

包含应返回其 getter 的属性名称的字符串。

### 返回值

绑定到指定属性的 getter 函数。如果找不到这样的属性或者该属性是数据属性，则返回 `undefined`。

描述
--

所有继承自 `Object.prototype` 的对象（也就是除了 `null` 原型对象的对象）都会继承 `__lookupGetter__()` 方法。如果为对象的属性定义了一个 getter，则无法通过该属性引用 getter 函数，因为该属性引用该函数的返回值。`__lookupGetter__()` 可用于获取对 getter 函数的引用。

`__lookupGetter__()` 沿着原型链向上查找指定的属性。如果原型链上的任何对象具有指定的自有属性，则返回该属性的属性描述符的 `get` 属性。如果该属性是数据属性，则返回 `undefined`。如果在整个原型链上都找不到该属性，也同样返回 `undefined`。

`__lookupGetter__()` 在规范中被定义为“可选规范”，这意味着不需要任何实现来实现它。然而，所有主要的浏览器都实现了它，并且由于它的持续使用，它不太可能被删除。如果一个浏览器实现了 `__lookupGetter__()`，那么它还需要实现 `__lookupSetter__()`、`__defineGetter__()` 和 `__defineSetter__()` 方法。

示例
--

### 使用 \_\_lookupGetter\_\_()


```js
const obj = {
  get foo() {
    return Math.random() > 0.5 ? "foo" : "bar";
  },
};

obj.\_\_lookupGetter\_\_("foo");
// [Function: get foo]
```

### 以标准方式查找属性的 getter

你应该使用 `Object.getOwnPropertyDescriptor()` API 来查找属性的 getter。与 `__lookupGetter__()` 相比，该方法允许查找 Symbol 属性。`Object.getOwnPropertyDescriptor()` 方法还适用于 `null` 原型对象，它们不继承自 `Object.prototype`，因此没有 `__lookupGetter__()` 方法。如果 `__lookupGetter__()` 沿着原型链向上查找属性的行为很重要，则可以使用 `Object.getPrototypeOf()` 自行实现它。


```js
const obj = {
  get foo() {
    return Math.random() > 0.5 ? "foo" : "bar";
  },
};

Object.getOwnPropertyDescriptor(obj, "foo").get;
// [Function: get foo]
```



```js
const obj2 = {
  \_\_proto\_\_: {
    get foo() {
      return Math.random() > 0.5 ? "foo" : "bar";
    },
  },
};

function findGetter(obj, prop) {
  while (obj) {
    const desc = Object.getOwnPropertyDescriptor(obj, "foo");
    if (desc) {
      return desc.get;
    }
    obj = Object.getPrototypeOf(obj);
  }
}

console.log(findGetter(obj2, "foo")); // [Function: get foo]
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.prototype.\_\_lookupGetter\_\_ |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.prototype.__lookupGetter__` 的 polyfill
* `Object.prototype.__lookupSetter__()`
* `get` 语法
* `Object.getOwnPropertyDescriptor()` 和 `Object.getPrototypeOf()`
* `Object.prototype.__defineGetter__()`
* `Object.prototype.__defineSetter__()`
* JS 指南：定义 Getter 和 Setter
Object.entries()
================

**`Object.entries()`** 静态方法返回一个数组，包含给定对象自有的可枚举字符串键属性的键值对。

尝试一下
----

语法
--


```js
Object.entries(obj)
```

### 参数

`obj`

一个对象。

### 返回值

一个由给定对象自有的可枚举字符串键属性的键值对组成的数组。每个键值对都是一个包含两个元素的数组：第一个元素是属性的键（始终是字符串），第二个元素是属性值。

描述
--

`Object.entries()` 返回一个数组，其元素是直接在 `object` 上找到相应的可枚举字符串键属性的键值对数组。这与使用 `for...in` 循环迭代相同，只是使用 `for...in` 循环也枚举原型链中的属性。`Object.entries()` 返回的数组顺序和 `for...in` 循环提供的顺序相同。

如果只需要属性的键，请使用 `Object.keys()`。如果只需要属性的值，请使用 `Object.values()`。

示例
--

### 使用 Object.entries()


```js
const obj = { foo: "bar", baz: 42 };
console.log(Object.entries(obj)); // [ ['foo', 'bar'], ['baz', 42] ]

// 类数组对象
const obj = { 0: "a", 1: "b", 2: "c" };
console.log(Object.entries(obj)); // [ ['0', 'a'], ['1', 'b'], ['2', 'c'] ]

// 具有随机键排序的类数组对象
const anObj = { 100: "a", 2: "b", 7: "c" };
console.log(Object.entries(anObj)); // [ ['2', 'b'], ['7', 'c'], ['100', 'a'] ]

// getFoo 是一个不可枚举的属性
const myObj = Object.create(
  {},
  {
    getFoo: {
      value() {
        return this.foo;
      },
    },
  },
);
myObj.foo = "bar";
console.log(Object.entries(myObj)); // [ ['foo', 'bar'] ]
```

### 在基本类型中使用 Object.entries()

非对象参数会强制转换成对象。`undefined` 和 `null` 不能被强制转换为对象，会立即抛出 `TypeError`。只有字符串可以有自己的可枚举属性，所有其他基本类型均返回一个空数组。


```js
// 字符串具有索引作为可枚举的自有属性
console.log(Object.entries("foo")); // [ ['0', 'f'], ['1', 'o'], ['2', 'o'] ]

// 其他基本类型（除了 undefined 和 null）没有自有属性
console.log(Object.entries(100)); // []
```

### 将 Object 转换成 Map

`Map()` 构造函数接受一个 `entries` 可迭代对象。使用 `Object.entries`，你可以很容易地将 `Object` 转换成 `Map`：


```js
const obj = { foo: "bar", baz: 42 };
const map = new Map(Object.entries(obj));
console.log(map); // Map(2) {"foo" => "bar", "baz" => 42}
```

### 遍历对象

使用数组解构语法，你可以很容易地遍历对象。


```js
// 使用 for...of 循环
const obj = { a: 5, b: 7, c: 9 };
for (const [key, value] of Object.entries(obj)) {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
}

// 使用数组方法
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});
```

规范
--

| Specification |
| --- |
| ECMAScript Language Specification # sec-object.entries |

浏览器兼容性
------

BCD tables only load in the browser with JavaScript enabled. Enable JavaScript to view data.

参见
--

* `core-js` 中 `Object.entries` 的 Polyfill
* 属性的可枚举性和所有权
* `Object.keys()`
* `Object.values()`
* `Object.prototype.propertyIsEnumerable()`
* `Object.create()`
* `Object.fromEntries()`
* `Object.getOwnPropertyNames()`
* `Map.prototype.entries()`