属性的可枚举性和所有者
自有属性——Own properties
hasOwnProperty、Object.getOwnPropertyNames…… 凡是强调 Own 指的是在对象本身上定义的属性,而不是从原型链上继承而来的。
... 展开操作符——浅拷贝语义
该操作符的目的是浅拷贝。
它主要分成两个场景,一个是在方括号 []
里面展开,一个是在花括号 {}
里面展开;前者遵从可迭代协议,使用对象的迭代器展开一个可迭代对象。但是,它还实现了一些扩展能力,它可以展开一个普通对象,其展开逻辑是可以认为是浅拷贝
js
const arr = [1, 2]
const arr2 = [2, 4]
//
const newArr = [...arr, ...arr2]
const obj = {
name: 'zs'
}
const zs = {
...obj,
age: 18
}
key 类型——name、symbol、#
对象的 key 可以有三种属性,key 类型为字符串的属性,key 类型为 symbol 类型的,而完全私有的 #
开头的属性,只有谷歌浏览器的控制台能够访问,其他的方法访问不了 🐶
js
Object.getOwnPropertyNames
Object.getOwnPropertySymbols
Object.getOwnPropertyDescriptors
可枚举属性——Enumerable
可枚举属性是指那些内部“可枚举”标志设置为 true 的属性,而平常我们在使用一些内置方法的时候,会默认将对象设置一些初始值
- 对于通过直接的赋值和属性初始化的属性,该标识值默认为即为 true;
- 对于通过
Object.defineProperty
等定义的属性,该标识值默认为 false; - 对于原型链上的方法默认为 false,而访问器默认为 true;这是由于使用 class 语法定义的类,其原型链上的方法默认是不可枚举的,该行为是根据 ES 规范决定的;
- Symbol 类型的 key 值的属性,默认为 false;
for..in 循环
对象的可枚举属性且为 string key,可以通过 for...in 循环进行遍历,该遍历包括对象自身的和继承的可枚举属性。
Descriptor
用于描述一个对象的某个 key 值所代表的属性的配置对象。
- value。该值表示该 key 值的属性的值。
- get。该函数使用一个空的参数列表,以便有权对值执行访问时,获取属性值。参见 getter。可能是 undefined。
- set。使用包含分配值的参数调用的函数。每当尝试更改指定属性时执行。参见 setter。可能是 undefined。
- enumerable。一个布尔值,表示是否可以通过 for...in 循环来枚举属性。另请参阅枚举性和属性所有权,以了解枚举属性如何与其他函数和语法交互。
- configurable
对象的私有属性实现方法
- 使用
_
开头的属性名,表示该属性是私有的,但是这种方式并不是真正的私有属性,只是约定俗成的,几乎没有限制,完全依赖于开发人员的意识,并且在使用for...in
时,_
开头的属性也会被遍历出来,这种行为很可能是我们不希望的。因此,不推荐使用。 - 使用
Symbol
类型作为属性名,因为Symbol
类型的属性名不会被for...in
遍历出来,并且Object.getOwnPropertyNames
也无法获取到Symbol
类型的属性名,但是Object.getOwnPropertySymbols
可以获取到Symbol
类型的属性名。比较推荐使用。 - 使用
WeakMap
类型实现,将一个类和一个WeakMap
实例关联起来,将类的实例作为WeakMap
的 key,将类的私有属性作为WeakMap
的 value,这样就可以实现类的私有属性,除了能够获得该WeakMap
,否则完全无法获取相应的属性,但是在实现上略微复杂,推荐使用。 - 使用
#
开头的属性名,这是 ES6 中新增的语法,表示该属性是私有的,并且该属性无法被for...in
遍历出来,也无法被Object.getOwnPropertyNames
获取到,但是Object.getOwnPropertyDescriptors
可以获取到#
开头的属性,但是即使 key 被获取到也无法在 class 外部访问。该种方式在和 Proxy、Reflect 一起使用时,非常容易发生错误,因此,不推荐使用。