属性的可枚举性和所有权
JavaScript 对象中的每个属性能根据三个因素进行分类:
- 可枚举或不可枚举;
- 字符串或 symbol;
- 自有属性或从原型链继承的属性。
可枚举属性是那些内部的可枚举标志设置为 true 的属性,对于通过直接赋值或属性初始化器创建的属性,该标识值默认为 true。对于通过 Object.defineProperty 等定义的属性,默认并不是可枚举的。大多数迭代方法(如:for...in 循环和 Object.keys)仅访问可枚举的键。
属性的所有权取决于属性是否直接属于该对象,而不是对象的原型链。
所有的属性,不论是可枚举或不可枚举、是字符串或 symbol、是自有的或继承的,都能用点记号表示法或方括号表示法进行访问。在本文,我们将专注于 JavaScript 提供的逐一访问一组对象属性的方法。
查询对象属性
有四种内置的查询对象属性的方法。它们全部都支持字符串和 symbol 键。下表总结了每个方法支持的类型。
| 可枚举的、自有的 | 可枚举的、继承的 | 不可枚举的、自有的 | 不可枚举的、继承的 | |
|---|---|---|---|---|
propertyIsEnumerable() |
true ✅ |
false ❌ |
false ❌ |
false ❌ |
hasOwnProperty() |
true ✅ |
false ❌ |
true ✅ |
false ❌ |
Object.hasOwn() |
true ✅ |
false ❌ |
true ✅ |
false ❌ |
in |
true ✅ |
true ✅ |
true ✅ |
true ✅ |
遍历对象属性
在 JavaScript 中有许多遍历对象属性的方法。有时候,属性作为数组返回;有时候,属性在循环中一个接着一个地迭代;有时候,属性用于构造或修改另一个对象。下表总结了属性能访问的情况。
仅访问字符串属性或仅访问 symbol 属性的方法有额外的注解。✅ 表示能访问这个类型的属性;❌ 表示不能访问这个类型的属性。
| 可枚举的、自有的 | 可枚举的、继承的 | 不可枚举的、自有的 | 不可枚举的、继承的 | |
|---|---|---|---|---|
Object.keysObject.valuesObject.entries |
✅ (字符串) |
❌ | ❌ | ❌ |
Object.getOwnPropertyNames |
✅ (字符串) |
❌ | ✅ (字符串) |
❌ |
Object.getOwnPropertySymbols |
✅ (symbol) |
❌ | ✅ (symbol) |
❌ |
Object.getOwnPropertyDescriptors |
✅ | ❌ | ✅ | ❌ |
Reflect.ownKeys |
✅ | ❌ | ✅ | ❌ |
for...in |
✅ (字符串) |
✅ (字符串) |
❌ | ❌ |
Object.assign(第一个参数之后) |
✅ | ❌ | ❌ | ❌ |
| 对象展开 | ✅ | ❌ | ❌ | ❌ |
通过可枚举性和所有权获取对象的属性
注:以下实现并非是适用于所有情况的最优算法,但可以快捷的展示语言特性。
- 使用
SimplePropertyRetriever.theGetMethodYouWant(obj).includes(prop)时将发生检测操作。 - 使用
SimplePropertyRetriever.theGetMethodYouWant(obj).forEach((value, prop) => {}));时将发生迭代操作。(或使用filter()、map()等方法)