属性的简洁表示
- ES6 允许在大括号里面,直接写入变量和函数,作为对象的属性和方法。
// 属性简写
const foo = 'bar';
const baz = {foo};
baz // {foo: "bar"} 属性名就是变量名,属性值就是变量值
// 等同于
const baz = {'foo': foo};
// 方法简写
const o = {
method() {
return "Hello!";
}
};
// 等同于
const o = {
method: function() {
return "Hello!";
}
};
- 简写的对象方法不能用于构造函数,会报错。
const obj = {
f() {
this.foo = 'bar';
}
};
new obj.f() // obj.f is not a constructor
属性名表达式
ES6 允许字面量定义对象时,用表达式作为对象的属性名,即把表达式放在方括号内。
let lastWord = 'last word';
const a = {
'first word': 'hello',
[lastWord]: 'world'
};
a['first word'] // "hello"
a[lastWord] // "world"
a['last word'] // "world"
// 表达式还可以定义方法名
let obj = {
['h' + 'ello']() {
return 'hi';
}
};
obj.hello() // hi
super
- ES6 新增
super关键字指向当前对象的原型对象。
const proto = {
foo: 'hello'
};
const obj = {
foo: 'world',
find() {
return super.foo; // 返回的是原型对象上的foo属性
}
};
Object.setPrototypeOf(obj, proto); // 将obj的原型对象修改为 proto
obj.find() // "hello"
super表示原型对象时,只能用在对象方法的简写法之中,其他地方都会报错。
// 报错
const obj = {
foo: super.foo
}
// 报错
const obj = {
foo: () => super.foo
}
// 报错
const obj = {
foo: function () {
return super.foo
}
}
// 正确
const obj = {
foo(){
super.foo;
}
}
扩展运算符
- 用于取出参数对象的所有可遍历属性,拷贝到当前对象之中。
let z = { a: 3, b: 4 };
let n = { ...z };
n // { a: 3, b: 4 }
// 数组也是特殊的对象
let foo = { ...['a', 'b', 'c'] };
foo // {0: "a", 1: "b", 2: "c"}
- 扩展运算符可以用于合并两个对象。
let ab = { ...a, ...b };
- 如果将扩展运算符作为对象赋值必须是最后一个参数,否则会报错。
let { ...x, y, z } = {x: 1, y: 2, a: 3, b: 4}; // 句法错误
let { x, ...y, ...z } = {x: 1, y: 2, a: 3, b: 4}; // 句法错误
let { x, y, ...z } = {x: 1, y: 2, a: 3, b: 4}; // 正确
z // {a: 3, b: 4}
静态方法
Object.is()
- 用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo') // true
Object.is({}, {}) // false
+0 === -0 // true
Object.is(+0, -0) // false 与严格相等的区别
NaN === NaN // false
Object.is(NaN, NaN) // true 与严格相等的区别
Object.assign()
- 用于对象的合并,将源对象的所有
可枚举、自身属性复制到目标对象。参数一是目标对象,后面的参数都是源对象。
const obj1 = {a: 1};
const obj2 = {b: 2};
const obj3 = {c: 3};
Object.assign(obj1, obj2, obj3);
obj1 // {a: 1, b: 2, c: 3}
- 如果源对象某个属性的值是对象,那么目标对象拷贝的是这个对象引用
浅拷贝。
const obj1 = {a: {b: 1}};
const obj2 = Object.assign({}, obj1);
obj1.a.b = 2;
obj2.a.b // 2
- 对于嵌套的对象,遇到同名属性会替换,而不是添加。
const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source) // { a: { b: 'hello' } }
常见用法
- 为对象添加属性。
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
- 为对象添加方法。
// 给原型对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});
- 克隆对象。
// 克隆对象自身值,不包含原型对象的值
function clone(origin){
return Object.assign({}, origin);
}
// 包含原型对象的值
function clone(origin){
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}
- 合并多个对象。
const merge = (target, ...sources) => Object.assign(target, ...sources);
- 为属性指定默认值。
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};
function processContent(options) {
options = Object.assign({}, DEFAULTS, options);
console.log(options);
}
processContent({logLevel: 1}) // {logLevel: 1, outputFormat: 'html'}
// DEFAULTS是默认值,但如果options有与之同名的属性,则options会覆盖
Object.values()
- 返回一个数组,成员是参数对象自身的所有可遍历的属性的值。
const obj = { foo: 'bar', baz: 42 };
Object.values(obj) // ["bar", 42]
Object.entries()
- 返回一个数组,成员是i参数对象自身的所有可遍历的属性的键值对。
const obj = { foo: 'bar', baz: 42 };
Object.entries(obj) // [ ["foo", "bar"], ["baz", 42] ]
Object.fromEntries()
- 此方法是
Object.entries的逆操作,用于将一个键值对数组转为对象。
let entries = [['name', '张三'], ['age', 18]];
Object.fromEntries(entries); // {name: '张三', age: 18}
Object.hasOwn()
- 用于判断某个属性是否为自身属性。参数一为要判断的对象;参数二为属性名。
const foo = Object.create({ a: 123 });
foo.b = 456;
Object.hasOwn(foo, 'a') // false a为foo继承的属性
Object.hasOwn(foo, 'b') // true b为原生的属性
- 此方法与
hasOwnProperty的区别是,对于不继承Object.prototype的对象不会报错,后者是会报错的。
const obj = Object.create(null);
obj.hasOwnProperty('foo') // 报错
Object.hasOwn(obj, 'foo') // false