一、对象扩展
1. 属性的简洁表示
大括号里面,直接写入变量和函数,作为对象的属性和方法。
以下是属性简写:直接写属性名(就自己等于属性值)
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"}// 等同于
const baz = {foo: foo};
以下是方法简写:直接省略冒号“:”和关键字function
const o = {method() {return "Hello!";}
};// 等同于const o = {method: function() {return "Hello!";}
};
案例:对象的简写:属性名=属性名:方法去除关键字和冒号
function getPoint() {const x = 1;const y = 10;return {x, y};
}getPoint()
// {x:1, y:10}
注意:对象中简写的函数不能当作构造函数使用
const obj = {f() {this.foo = 'bar';} };new obj.f() // 报错
2. 属性名表达式
但是在通过对象定义属性时候:允许通过表达式(被【】包裹的表达式作为属性名)
// 方法一
obj.foo = true;// 方法二
obj['a' + 'bc'] = 123;
在创建字面量对象定义属性时候:ES5中只允许使用标识符进行作为属性名
var obj = {
// foo和zbc都是标识符foo: true,abc: 123
};
但是在ES6创建字面量定义属性:可以使用表达式(一定被【】或者‘’包裹起来)
let lastWord = 'last word';const a = {'first word': 'hello',[lastWord]: 'world'
};a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
注意:属性名的表达式和简介表达式 同时使用会报错
// 报错
const foo = 'bar';
const bar = 'abc';
const baz = { [foo] };// 正确
const foo = 'bar';
const baz = { [foo]: 'abc'};
3. 遍历对象的五种方法(暂时学习两种):
for...in
for...in
循环遍历对象自身的和继承的可枚举属性
Object.keys(obj)
返回一个数组,包括对象自身的(不含继承的)所有可枚举属性
4. super关键字
this
关键字总是指向函数所在的当前对象,ES6 又新增了另一个类似的关键字super
,指向当前对象的原型对象注意:只能用在对象的方法之中,用在其他地方都会报错。
const proto = {foo: 'hello'
};const obj = {foo: 'world',find() {return super.foo;}
};Object.setPrototypeOf(obj, proto);
obj.find() // "hello"
// 报错
const obj = {foo: super.foo
}// 报错
const obj = {foo: () => super.foo
}// 报错
const obj = {foo: function () {return super.foo}
}
5 解构赋值
let { x, y, ...z } = { x: 1, y: 2, a: 3, b: 4 };
x // 1
y // 2
z // { a: 3, b: 4 }
解构赋值时候:
- 如果等号右边是
undefined
或null
,就会报错,因为它们无法转为对象- 解构赋值必须是最后一个参数,否则会报错。
let { ...z } = null; // 运行时错误
let { ...z } = undefined; // 运行时错误
解构赋值的拷贝是浅拷贝,即如果一个键的值是复合类型的值(数组、对象、函数)、那么解构赋值拷贝的是这个值的引用,而不是这个值的副本
let obj = { a: { b: 1 } };
let { ...x } = obj;
obj.a.b = 2;
x.a.b // 2
扩展运算符的解构赋值,不能复制继承自原型对象的属
let o1 = { a: 1 };
let o2 = { b: 2 };
o2.__proto__ = o1;
let { ...o3 } = o2;
o3 // { b: 2 }
o3.a // undefined
二、对象新增方法
1. Object.is()
比较两个值是否严格相等:
- 弥补NaN不等于自身问题
- 弥补-0不等于+0问题
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
2. Object.assign()
对象的合并
注意:属性同名后面覆盖前面
const target = { a: 1, b: 1 };const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}
//数组替换案例:
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]
不是对象转为对象
typeof Object.assign(2) // "object"
实行的是浅拷贝:源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用
常见用途
- 为对象添加属性
- 为对象添加方法
- 合并多个对象
- 克隆对象
function clone(origin) {return Object.assign({}, origin); }
3.__proto__属性
如果一个对象本身部署了
__proto__
属性,该属性的值就是对象的原型
Object.getPrototypeOf({ __proto__: null })
// null
4.Object.keys()
返回对象的键名返回为数组
var obj = { foo: 'bar', baz: 42 };
Object.keys(obj)
// ["foo", "baz"]
5.Object.values()
返回对象的键值返回为数组
const obj = { foo: 'bar', baz: 42 };
Object.values(obj)
// ["bar", 42]
6. Object.entries()
返回对象的键值对返回为数组(嵌套)
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj)
// [ ["foo", "bar"], ["baz", 42] ]
7. Object.fromEntries()
将数组嵌套转为对象
Object.fromEntries([['foo', 'bar'],['baz', 42]
])
// { foo: "bar", baz: 42 }