# ES6之对象的扩展
# 一. 属性的简洁表示
在ES6中,当属性名与属性值相同时,可省略属性值。
// 属性简写
let a = 'bar';
let b = {a};
b // {a: "bar"}
// 等同于
let b = {a: a};
// 方法简写
let obj = {
method() {
return "Hello World!";
}
};
// 等同于
let obj = {
method: function() {
return "Hello World!";
}
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
以下是实际场景
let age = 29;
let user = {
name: '浪子快跑',
//等同于age: age
age,
// 等同于say: function ()...
say() { console.log('my name is', this.name); }
};
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
简写的对象方法不能用作构造函数,会报错
const obj = {
f() {
this.foo = 'bar';
}
};
new obj.f() // 报错
1
2
3
4
5
6
7
2
3
4
5
6
7
# 二. 属性名表达式
ES6 允许字面量定义对象时,用(表达式)作为对象的属性名,即把表达式放在方括号内
let key = 'foo';
let obj = {
[key]: true,
['a' + 'bc']: 123
};
console.log(obj1.foo, obj1.abc) // true 123
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
注意
- 属性名表达式与简洁表示法,不能同时使用,会报错
// 报错
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };
// 正确
const foo = 'bar';
const baz = { [foo]: 'abc'};
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
- 属性名表达式如果是一个对象,默认情况下会自动将对象转为字符串[object Object]
const key1 = {a: 1};
const key2 = {b: 2};
const obj = {
[key1]: 'valueA',
[key2]: 'valueB'
};
obj // Object {[object Object]: "valueB"}
// [key1]和[key2]得到的都是[object Object],
// 所以[key2]会把[key1]覆盖掉,而obj最后只有一个[object Object]属性。
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
# 三. 可枚举性
对象的每个属性都有一个描述对象,用来控制该属性的行为。
Object.getOwnPropertyDescriptor
方法可以获取该属性的描述对象。
let obj = { foo: 123 };
Object.getOwnPropertyDescriptor(obj, 'foo')
// {
// value: 123,
// writable: true,
// enumerable: true,
// configurable: true
// }
1
2
3
4
5
6
7
8
2
3
4
5
6
7
8
目前,有四个操作会忽略enumerable为false的属性。
for...in循环:只遍历对象自身的和继承的可枚举的属性。
Object.keys():返回对象自身的所有可枚举的属性的键名。
JSON.stringify():只串行化对象自身的可枚举的属性。
Object.assign(): 忽略enumerable为false的属性,只拷贝对象自身的可枚举的属性。
# 四. super 关键字
ES6 新增了关键字super
,指向当前对象的原型对象。
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo;
}
};
Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
1
2
3
4
5
6
7
8
9
10
11
12
13
2
3
4
5
6
7
8
9
10
11
12
13
注意:super
关键字表示原型对象时,只能用在对象的方法之中,用在其他地方都会报错。
// 报错
const obj = {
foo: super.foo
}
// 报错
const obj = {
foo: () => super.foo
}
// 报错
const obj = {
foo: function () {
return super.foo
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
下面代码中,super.foo指向原型对象proto的foo方法,但是绑定的this却还是当前对象obj,因此输出的是world。
const proto = {
x: 'hello',
foo() {
console.log(this.x);
},
};
const obj = {
x: 'world',
foo() {
super.foo();
}
}
Object.setPrototypeOf(obj, proto);
obj.foo() // "world"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 五. 对象的扩展运算符
####1. 扩展运算符 对象的扩展运算符(...)用于取出参数对象的所有可遍历属性,然后拷贝到当前对象之中。
let a = {x:1, y:2}
let b = {...a}
// b = {x:1, y:2}
// 合并两个对象,当有相同属性时,后面的覆盖前面的
let a = {x:1, y:2}
let b = {x1:3, y:4}
let c = {...a, ...b}
// c = {x: 1, y: 4, x1: 3}
// 对象的扩展运算符后面可以跟表达式
const obj = {
...(x > 1 ? {a: 1} : {}),
b: 2,
};
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
2
3
4
5
6
7
8
9
10
11
12
13
14
15
注意:对象的扩展运算符,只会返回参数对象自身的、可枚举的属性
#####2. 解构赋值
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
// 解构赋值时右边需是一个对象,否则报错
let { ...z } = null; // 运行时错误
let { ...z } = undefined; // 运行时错误
// 解构赋值必须是最后一个参数
let { ...x, y, z } = someObject; // 句法错误
let { x, ...y, ...z } = someObject; // 句法错误
// 扩展运算符的解构赋值,不能复制继承自原型对象的属性
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
注:本文只记录了日常开发中常用的更新