Object.assign()方法用于从一个或多个源对象(sources)中拷贝所有可枚举的自有属性到目标对象(target),并返回目标对象。拷贝过程中将调用源对象的getter方法,并在target对象上使用setter方法实现目标对象的拷贝。
1 | Object.assign(target, ...sources) |
不过,采用这种方法克隆,只能克隆原始对象自身的值,不能克隆它继承的值。如果想要保持继承链,可以采用下面的代码。
原文:Both String and Symbol properties are copied.
String和Symbol类型都可被直接分配。
1234 | function (origin) { let originProto = Object.getPrototypeOf(origin); return Object.assign(Object.create(originProto), origin);} |
注意:如果属性是只读的,那将会抛出异常,目标对象将会停止改变(而之前的改变会保留)。但是对于null或者undefind会直接忽略。
简单克隆对象
1234 | var obj = ;var copy = Object.assign({}, obj);console.log(copy); //Object {a: 1} |
合并对象
123456 | 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属性
12345 | var a = {x: 1};var b = {[Symbol('y')]: 2};var obj = Object.assign(a, b);console.log(obj); //Object {x: 1, Symbol(y): 2} |
继承的属性和不可枚举的属性不会被拷贝
1234567891011121314 | 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
12345678910111213 | 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"} |
只读属性不能被拷贝
12345678910111213 | 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); // 2console.log(target.foo2); // 3console.log(target.foo); // 1console.log(target.foo3); // undefinedconsole.log(target.baz); // undefined |
拷贝属性的赋值器(setter)和取值器(getter)
123456789101112 | 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
1234567891011121314151617181920212223 | 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; //最终输出 }; })();} |
不支持深度拷贝
1234 | var target = { a: { b: 'c', d: 'e' } }var source = { a: { b: 'hello' } }Object.assign(target, source)// { a: { b: 'hello' } } |
深度拷贝
拷贝数组
1234 | 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