属性的简单表示
ES 6
允许将属性写在 {}
中,直接写入变量和函数,作为对象的属性和方法。这样的书写方式更加简洁。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const foo = 'foo'; function getName() { console.log('name'); } const obj = { foo, getName };
console.log(obj);
const obj = { foo: 'foo', getName: function () { console.log('name'); }, }; console.log(obj);
|
属性的可枚举性和遍历
可枚举性
对象的每个属性都有一个描述对象,用来控制该属性的行为。
Object.getOwnPropertyDescriptor
方法来获取该属性的描述对象。
1 2 3 4 5 6 7 8
| const obj = { x: 1 }; console.log(Object.getOwnPropertyDescriptor(obj));
|
描述对象的 enumerable
属性,称为可枚举性,如果该属性为 false
,就会被某些操作忽略。
操作会忽略 enumerable
为 false
的属性。
for...in
循环:遍历对象自身和继承的可枚举属性。
Object.keys()
:返回对象所有可枚举的属性的 key
。
JSON.stringify()
:只串行化对象自身的可枚举的属性。
Object.assign()
:只拷贝对象自身的可枚举属性。
属性遍历
- for…in
for...in
循环对象自身的和继续的可枚举属性
1 2 3 4 5 6 7
| const obj = { x: 1, y: 2, z: 3 }; for (let o in obj) { console.log(o); }
|
- Object.keys(obj)
Object.keys(obj)
返回一个数组,包含所有可枚举属性的 key
。
1 2 3 4 5 6 7
| const obj = { x: 1, y: 2, z: 3 }; for (let o of Object.keys(obj)) { console.log(o); }
|
- Object.getOwnPropertyNames(obj)
Object.getOwnPropertyNames(obj)
返回一个数组,包含对象自身的所有属性的 key
。
1 2 3 4 5 6 7
| const obj = { x: 1, y: 2, z: 3 }; for (let o of Object.getOwnPropertyNames(obj)) { console.log(o); }
|
- Object.getOwnPropertySymbols(obj)
Object.getOwnPropertySymbols(obj)
返回一个数组,包含对象自身的所有 Symbol
属性的 key
。
打印的属性均为 Symbol
。
1 2 3
| const obj = { [Symbol('x')]: 1, y: 2, z: 3 }; console.log(Object.getOwnPropertySymbols(obj));
|
- Reflect.ownKeys(obj)
Reflect.ownKeys(obj)
返回一个数组,包含对象自身所有键名,不管键名是 Symbol
或字符串,也不管是否可枚举。
1 2 3
| const obj = { [Symbol('x')]: 1, y: 2, z: 3, 1: 10, 2: 11 }; console.log(Reflect.ownKeys(obj));
|
一共五种遍历 key
的方式,但是遍历的次序是有规则的。
- 首先遍历所有数值,并按照升序排列
- 其次遍历字符串,按照加入时间升序
- 最后才是
Symbol
,按照加入时间升序
对象的扩展运算符
在 解构赋值 和 数组的扩展 中,我们分别提到过对象的解构赋值以及扩展运算符。
我们来看看扩展运算符在对象中的使用。
解构赋值
我们来回顾一下 解构赋值 。
1 2 3
| const { x, y } = { x: 1, y: 2 }; console.log(x); console.log(y);
|
- 使用扩展运算符时需要注意的是,解构赋值必须是最后一个参数且只能有一个,否则报错。
1 2 3 4 5 6
| const { x, ...obj } = { x: 1, y: 2, z: 3 }; console.log(x); console.log(obj);
const { ...obj, z } = { x: 1, y: 2, z: 3 }; console.log(obj);
|
- 对象的解构赋值右侧不能是
undefined
或 null
,会报错
1 2 3
| const { ...obj } = null; const { ...obj } = undefined;
|
扩展运算符
对象的扩展运算符用于取出参数对象的所有可便利属性,拷贝到当前对象之中。
1 2 3
| const obj = { x: 1, y: 2 }; const obj2 = { ...obj }; console.log(obj);
|
- 数组也是特殊的对象,所以对象的扩展运算符也可以用于数组。
1 2 3
| const obj = { ...['1', '2', '3'] }; console.log(obj);
|
1 2
| const obj = { ...{}, x: 1 }; console.log(obj);
|
- 如果扩展运算符并不是对象,则会被自动转化成对象,但是部分值没有自身属性,所以会返回一个空对象
{}
。
1 2 3 4
| const obj = { ...1 }; const obj2 = { ...true }; const obj3 = { ...undefined }; const obj4 = { ...null };
|
1 2
| const obj = { ...'hzq' }; console.log(obj);
|
对象新增的常用实例方法
Object.is()
Object.is()
是用来判断两个是否严格相等,与严格比较运算符 ===
行为基本一致。
1 2 3
| console.log(Object.is('hello', 'world')); console.log(Object.is('hello', 'hello')); console.log(Object.is({}, {}));
|
与 ===
不同点
1 2 3 4 5
| console.log(+0 === -0); console.log(NaN === NaN);
console.log(Object.is(+0, -0)); console.log(Object.is(NaN, NaN));
|
Object.assign()
Object.assign()
放啊主要用于对象的合并,将对象的所有可枚举属性复制到目标对象。
1 2 3 4 5 6
| const obj = {}; const obj1 = { x: 1 }; const obj2 = { y: 2 }; Object.assign(obj, obj1, obj2); console.log(obj);
|
从上面我们可以看出,第一个参数就是目标对象,将后面对象的所有可枚举属性复制到第一个参数。
- 如果后面参数中,有同名属性,则目标对象中的值,会被新的对象替代
- 如果只有一个参数,则直接返回该参数
1 2 3 4 5 6 7 8 9 10
| const obj = { x: 1 }; const obj1 = { x: 3, y: 2 }; const obj2 = { y: 4 }; Object.assign(obj, obj1, obj2); console.log(obj);
const obj3 = { x: 3 }; console.log(Object.assign(obj3) === obj3);
|
- 如果参数不是对象,会被转成对象,然后返回
undefined
和 null
无法转成对象,会报错
1 2 3 4 5 6
| console.log(Object.assign(1));
console.log(typeof Object.assign(1));
console.log(Object.assign(undefined)); console.log(Object.assign(null));
|
Object.keys(),Object.values(),Object.entries()
Object.keys()
Obejct.keys()
是 ES 5
引入的,我们还是在这里稍微提一下。Object.keys()返回对象键值的数组,然后用来遍历对象的 key。
1 2 3 4 5 6 7
| const obj = { x: 1, y: 2, z: 3 }; for (let key of Object.keys(obj)) { console.log(key); }
|
Object.values()
Object.values()
是 ES 6
时引入的,返回一个数组,是每个键对应的值。返回值的顺序可以参照,对象的可枚举性中顺序。
当然许多特性是类似的。
- 返回的是可遍历的值,
enumerable
为 true
- 如果转化的值不是对象,则会先转化为对象。
- 字符串会被转为数组输出,
- 布尔值、数值都不会为实例添加非继承的属性,返回空数组
Symbol
作为 key
会被忽略
1 2 3 4 5 6 7 8 9 10 11 12 13
| const objVal = { 1: 'a', 2: 'b', 7: 'c' }; console.log(Object.values(objVal));
const obj = { [Symbol()]: 1, x: 2, y: 3 }; console.log(Object.values(obj));
const str = 'hello'; console.log(Object.values(str));
console.log(Object.values(true));
console.log(Object.values(11));
|
Object.entries()
Object.entries()
方法返回一个数组,成员是参数对象自身的所有可遍历属性的键值对数组。
1 2 3
| const obj = { x: 1, y: 2, z: 3 }; console.log(Object.entries(obj));
|
- 对象的属性名是一个
Symbol
值,该属性会被忽略。
1 2 3
| const obj = { [Symbol()]: 1, x: 2 }; console.log(Object.entries(obj));
|
两个用途
1 2 3 4 5 6
| const obj = { x: 1, y: 2 }; for (let [k, v] of Object.entries(obj)) { console.log(`key = ${k}, val = ${v}`); }
|
1 2 3 4
| const obj = { x: 1, y: 2 }; const map = new Map(Object.entries(obj)); console.log(map);
|
Object.fromEntries()
Object.fromEntries()
是 Object.entries()
的逆向操作,用于将一个键值对数组转为对象。
1 2 3 4 5 6 7
| const arr = [ ['x', 1], ['y', 2], ['z', 3], ]; console.log(Object.fromEntries(arr));
|
用途
主要作用就是,是将键值对的数据结构还原为对象
1 2 3 4 5 6
| let map = new Map(); map.set('x', 1); map.set('y', 2); map.set('z', 3); console.log(Object.fromEntries(map));
|
对象的扩展,我们就先介绍到这里,如果有问题,会对文章进行更新。
感谢各位的观看!