您的位置:首页 > 其它

【ES6】对象的扩展2

2016-09-13 07:51 211 查看
Object.assign
方法实行的是浅拷贝,而不是深拷贝。也就是说,如果源对象某个属性的值是对象,那么目标对象拷贝得到的是这个对象的引用。

var obj1 = {a: {b: 1}};
var obj2 = Object.assign({}, obj1);

obj1.a.b = 2;
obj2.a.b // 2


上面代码中,源对象
obj1
a
属性的值是一个对象,
Object.assign
拷贝得到的是这个对象的引用。这个对象的任何变化,都会反映到目标对象上面。

对于这种嵌套的对象,一旦遇到同名属性,
Object.assign
的处理方法是替换,而不是添加。
var target = { a: { b: 'c', d: 'e' } }
var source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }


上面代码中,
target
对象的
a
属性被
source
对象的
a
属性整个替换掉了,而不会得到
{
a: { b: 'hello', d: 'e' } }
的结果。这通常不是开发者想要的,需要特别小心。

有一些函数库提供
Object.assign
的定制版本(比如Lodash的
_.defaultsDeep
方法),可以解决浅拷贝的问题,得到深拷贝的合并。

注意,
Object.assign
可以用来处理数组,但是会把数组视为对象。
Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]


上面代码中,
Object.assign
把数组视为属性名为0、1、2的对象,因此目标数组的0号属性
4
覆盖了原数组的0号属性
1


常见用途

Object.assign
方法有很多用处。

(1)为对象添加属性
class Point {
constructor(x, y) {
Object.assign(this, {x, y});
}
}


上面方法通过
Object.assign
方法,将
x
属性和
y
属性添加到
Point
类的对象实例。

(2)为对象添加方法
Object.assign(SomeClass.prototype, {
someMethod(arg1, arg2) {
···
},
anotherMethod() {
···
}
});

// 等同于下面的写法
SomeClass.prototype.someMethod = function (arg1, arg2) {
···
};
SomeClass.prototype.anotherMethod = function () {
···
};


上面代码使用了对象属性的简洁表示法,直接将两个函数放在大括号中,再使用assign方法添加到SomeClass.prototype之中。

(3)克隆对象
function clone(origin) {
return Object.assign({}, origin);
}


上面代码将原始对象拷贝到一个空对象,就得到了原始对象的克隆。

不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。
function clone(origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign(Object.create(originProto), origin);
}


(4)合并多个对象

将多个对象合并到某个对象。
const merge =
(target, ...sources) => Object.assign(target, ...sources);


如果希望合并后返回一个新对象,可以改写上面函数,对一个空对象合并。
const merge =
(...sources) => Object.assign({}, ...sources);


(5)为属性指定默认值
const DEFAULTS = {
logLevel: 0,
outputFormat: 'html'
};

function processContent(options) {
let options = Object.assign({}, DEFAULTS, options);
}


上面代码中,
DEFAULTS
对象是默认值,
options
对象是用户提供的参数。
Object.assign
方法将
DEFAULTS
options
合并成一个新对象,如果两者有同名属性,则
option
的属性值会覆盖
DEFAULTS
的属性值。

注意,由于存在深拷贝的问题,
DEFAULTS
对象和
options
对象的所有属性的值,都只能是简单类型,而不能指向另一个对象。否则,将导致
DEFAULTS
对象的该属性不起作用。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: