1. 对象属性的可枚举性和遍历
let obj = { a: 1};
Object.getOwnPropertyDescriptor(obj, 'a')
// configurable: true
// enumerable: true
// value: 1
// writable: true
「enumerable」属性成为「可枚举性」,如果该属性为false,有一些操作会省略当前属性。
有四个操作会忽略enumerable为false的属性。
- 「for...in」循环:只遍历对象「自身」和「继承」的可枚举属性。
- 「Object.keys()」:返回对象「自身」的所有可枚举的属性的「键名」。
- 「JSON.stringify()」:只串行化对象「自身」的可枚举属性。
- 「Object.assign()」:忽略「enumerable」为false的属性,只拷贝对象「自身」的可枚举的属性。
属性的遍历
- 「for...in」遍历对象「自身」和「继承」的可枚举属性。(不包括Symbol属性)
- 「Object.keys()」返回一个数组,包括对象「自身」的(不包括继承的)所有可枚举属性的键名。(不包括Symbol属性)
- 「Object.getOwnPropertyNames(obj)」, 返回一个数组,包含对象「自身」的所有属性的键名。(不包括Symbol属性,但是包含不可枚举的属性)
- 「Object.getOwnPropertySymbols(obj)」,返回一个数组,包含对象「自身」的所有Symbol属性的键名。
- 「Reflect.ownKeys(obj)」,返回一个数组,包括对象「自身」的所有键名。(不管键名是否为Symbol值,不管是否可枚举)。
2. 扩展字符串
解构赋值是「浅拷贝」,即如果一个键的值是复合类型的值(数组,对象、函数),那么解构赋值拷贝的是这个值的引用,而不是这个值的副本。
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
扩展运算符的解构赋值,不能复制继承自「原型对象」的属性。
const o = Object.create({ x: 1, y: 2 });
o.z = 3;
let { x, ...newObj } = o;
let { y, z } = newObj;
x // 1
y // undefined
z // 3
对象的解构赋值等同于使用「Object.assign()」方法。
let aClone = { ...a };
// 等同于
let bClone = Object.assign({}, a);
上面这个例子只是拷贝了对象实例的属性,如果想完全克隆一个对象,还要拷贝对象原型的属性。
// 写法一
const clone2 = Object.assign(
Object.create(Object.getPrototypeOf(obj)), // Object.getPrototypeOf(),返回原型对象
obj
);
// 写法二
const clone3 = Object.create(
Object.getPrototypeOf(obj),
Object.getOwnPropertyDescriptors(obj)
)
网友评论