理解Object.assign

Object.assign()方法用于从一个或多个源对象(sources)中拷贝所有可枚举的自有属性到目标对象(target),并返回目标对象。拷贝过程中将调用源对象的getter方法,并在target对象上使用setter方法实现目标对象的拷贝。

      
      
1
      
      
Object .assign( target, .. .sources)

不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。

原文:Both String and Symbol properties are copied.

String和Symbol类型都可被直接分配。

      
      
1
2
3
4
      
      
function (origin) {
let originProto = Object.getPrototypeOf(origin);
return Object.assign( Object.create(originProto), origin);
}

注意:如果属性是只读的,那将会抛出异常,目标对象将会停止改变(而之前的改变会保留)。但是对于null或者undefind会直接忽略。

简单克隆对象

      
      
1
2
3
4
      
      
var obj = ;
var copy = Object.assign( {}, obj);
console.log( copy); //Object {a: 1}

合并对象

      
      
1
2
3
4
5
6
      
      
var a = {x: 1};
var b = {y: 2};
var c = {x: 4, z: 3};
var obj = Object.assign(a, b, c);
console.log(obj); //Object {x: 4, y: 2, z: 3}

拷贝Symbol属性

      
      
1
2
3
4
5
      
      
var a = {x: 1};
var b = {[ Symbol( 'y')]: 2};
var obj = Object.assign(a, b);
console.log(obj); //Object {x: 1, Symbol(y): 2}

继承的属性和不可枚举的属性不会被拷贝

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
      
      
var obj = Object.create({foo: 1}, //继承的对象, obj.__proto__ == {foo: 1}
{
a: { //不可枚举的
value: 2
},
b: {
value: 3,
enumerable: true //可枚举的
}
}
);
var copy = Object.assign({}, obj);
console.log(copy); //Object {b: 3}

字符串会被转成object

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
      
      
var str = 'hejx';
var obj = Object.assign({}, str);
console.log(obj); //Object {0: "h", 1: "e", 2: "j", 3: "x"}
var a = "123";
var b = false;
var c = 123;
var d = Symbol( 'sy');
var e = Object.assign({}, a, b, c, d, null, undefined);
//null和undefined会被忽略,在这里只有a(字符串)可以被枚举并被转成对象,如果存在2个字符串,将会报错
console.log(e); //Object {0: "1", 1: "2", 2: "3"}

只读属性不能被拷贝

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
      
      
var target = Object.defineProperty({}, 'foo', {
value: 1,
writable: f 大专栏  理解Object.assignalse
}); // target.foo是只读属性
Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// 这里会抛出异常,但是在错误之前,目标对象的部分属性已经被改变或者新增,而后续的将不会再进行拷贝
console.log(target.bar); // 2
console.log(target.foo2); // 3
console.log(target.foo); // 1
console.log(target.foo3); // undefined
console.log(target.baz); // undefined

拷贝属性的赋值器(setter)和取值器(getter)

      
      
1
2
3
4
5
6
7
8
9
10
11
12
      
      
var obj = {
a: 1,
get b(){
return 2;
},
someMethod(){ //同样会被拷贝,可以用于为对象添加方法
//someMethod
}
};
var copy = Object.assign({}, obj);
console. log( copy); // Object {a: 1, b: 2, someMethod: function(){}}

es5版本的Object.assign

不支持Symbol属性,因为es5压根没有Symbol

      
      
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
      
      
if ( typeof Object.assign != 'function') { //判断是否支持
( function () {
Object.assign = function (target) {
;
if (target === undefined || target === null) {
throw new TypeError( 'Cannot convert undefined or null to object');
}
var output = Object(target);
for ( var index = 1; index < arguments.length; index++) {
var source = arguments[index];
if (source !== undefined && source !== null) {
for ( var nextKey in source) {
if (source.hasOwnProperty(nextKey)) { //判断一个属性是定义在对象本身而不是继承自原型链
output[nextKey] = source[nextKey];
}
}
}
}
return output; //最终输出
};
})();
}

不支持深度拷贝

      
      
1
2
3
4
      
      
var target = { a: { b: 'c', d: 'e' } }
var source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

深度拷贝

拷贝数组

      
      
1
2
3
4
      
      
var arr = [ 1, 2, 3]; //会被当成对象
var str = "4567";
var copy = Object.assign({}, arr, str);
console. log( copy); // Object { 0: "4", 1: "5", 2: "6", 3: "7"}

兼容性

属于es6规范,然而兼容性并不好,pc端除了ie,其他都支持。移动端目前就Firefox Mobile 支持。

文献

摘自developer.mozilla.org

es6.ruanyifeng.com

ES2015系列(二) 理解Object.assign

猜你喜欢

转载自www.cnblogs.com/wangziqiang123/p/11691221.html