object-assign合并对象
1. Object.assign()
对于合并对象操作, ECMAScript 6 中提供了一个函数:
Object.assign(target, source);
这个方法会将所有可枚举 [1] 的自由属性从 source
复制到 target
。并且它返回(修改后的) target
。关于这个函数最终签名至今还在争论,最终还有可能支持多个来源(被复制的对象)。即便是使用简单的签名(signature),也可以处理多个来源,使用Array.prototype.reduce
:
[source1, source2 source3].reduce(Object.assign, target);
1.1 属性名:字符串或者符号
在 ECMAScript 6中,属性名称可以是字符串或者 符号 (symbols)。后者是一种新的唯一标识符;基本上使用符号作为属性名是不可能有命名冲突的。Object.assign()
支持字符串或者符号作为属性名。
原文中叫做: property keys, 表示对象的键,属性就干脆译作属性名。如有误,请指正。
1.2 复制与赋值
目标对象中的属性是通过赋值操作创建的(内置的[[Put]]操作)。这就意味着如果target
拥有(自身或者继承的) setters [1] ,这回在复制的过程中调用。一种可替代的方式就是定义新的属性 [2] ,总是创建新的自由属性而从不调用 setters。原本对于Object.assign()
的一个变体的提议就是使用定义替代赋值的方式。但是该提议被 ECMAScript 6 拒绝了(在后续新版中可能会重新考虑)。
2. Object.assign() 用例
2.1 设置实例属性
构造器的任务就是设置实例属性。对于这个任务来说变量名总是被认为是冗余的:
class Point {
constructor(x, y) {
this.x = x;
this.y = y;
}
}
我比较喜欢下面的语法,它完全删除了冗余的代码(CoffeeScript 和 TypeScript都可以做到,但是我更喜欢下面这种语法):
class Point {
constructor(this.x, this.y) {
}
}
Object.assign()
至少也能够让你避免一些冗余:
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}
在 ECMAScript 6 中, {x, y}
是 {x: x, y: y}
的一种缩写形式。
2.2 给对象添加方法
在 ECMAScript 5 中,可以使用函数表达式来给对象添加方法:
MyClass.prototype.foo = function(arg1, arg2) {
// ...
};
在 ECMAScript 6 中对于方法 [3] 有一个更简洁的语法。这就要感谢Object.assign()
了,但是你也不必抛弃原来的语法:
Object.assign(MyClass.prototype, {
foo(arg1, arg2) {
...
}
});
2.3 克隆对象
也可以使用 Object.assign()
来克隆一个对象(浅克隆):
var copy = Object.assign({__proto__: obj.__proto__}, obj);
如果只对对象的自由属性感兴趣,那更简单:
var copy = Object.assign({}, obj);
参考
[1]. JavaScript中的对象属性
[3]. ECMAScript 6中可调用的实体
https://github.com/sindresorhus/object-assign/blob/master/index.js