语法
Object.assign(target, ...sources)
参数
target
- 目标对象。
sources
- 源对象。
返回值
目标对象。
描述
如果目标对象中的属性具有相同的键,则属性将被源中的属性覆盖。后来的源的属性将类似地覆盖早先的属性。
Object.assign
方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]
和目标对象的[[Set]]
,所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()
和Object.defineProperty()
。
String
类型和 Symbol
类型的属性都会被拷贝。
在出现错误的情况下,例如,如果属性不可写,会引发TypeError
,如果在引发错误之前添加了任何属性,则可以更改target
对象。
注意,Object.assign
会跳过那些值为 null
或 undefined
的源对象。
示例
复制一个对象
-
-
var copy = Object.assign({}, obj);
-
深拷贝问题
针对深拷贝,需要使用其他方法,因为 Object.assign()
拷贝的是属性值。假如源对象的属性值是一个指向对象的引用,它也只拷贝那个引用值。
-
-
-
-
let obj1 = { a: 0 , b: { c: 0}};
-
let obj2 = Object.assign({}, obj1);
-
console.log(JSON.stringify(obj2));
-
-
-
console.log(JSON.stringify(obj1));
-
console.log(JSON.stringify(obj2));
-
-
-
console.log(JSON.stringify(obj1));
-
console.log(JSON.stringify(obj2));
-
-
-
console.log(JSON.stringify(obj1));
-
console.log(JSON.stringify(obj2));
-
-
-
obj1 = { a: 0 , b: { c: 0}};
-
let obj3 = JSON.parse(JSON.stringify(obj1));
-
-
-
console.log(JSON.stringify(obj3));
-
-
-
合并对象
-
-
-
-
-
var obj = Object.assign(o1, o2, o3);
-
-
合并具有相同属性的对象
-
var o1 = { a: 1, b: 1, c: 1 };
-
-
-
-
var obj = Object.assign({}, o1, o2, o3);
-
属性被后续参数中具有相同属性的其他对象覆盖。
拷贝 symbol 类型的属性
-
-
var o2 = { [Symbol('foo')]: 2 };
-
-
var obj = Object.assign({}, o1, o2);
-
-
Object.getOwnPropertySymbols(obj);
继承属性和不可枚举属性是不能拷贝的
-
var obj = Object.create({foo: 1}, {
-
-
-
-
-
-
-
-
-
-
var copy = Object.assign({}, obj);
-
原始类型会被包装为对象
-
-
-
-
-
-
var obj = Object.assign({}, v1, null, v2, undefined, v3, v4);
-
-
-
异常会打断后续拷贝任务
-
var target = Object.defineProperty({}, "foo", {
-
-
-
-
-
Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
-
-
-
-
-
console.log(target.foo2);
-
-
console.log(target.foo3);
-
拷贝访问器
-
-
-
-
-
-
-
-
var copy = Object.assign({}, obj);
-
-
-
-
-
-
functioncompleteAssign(target,...sources){
-
sources.forEach(source => {
-
let descriptors = Object.keys(source).reduce((descriptors, key)=> {
-
descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
-
-
-
-
-
Object.getOwnPropertySymbols(source).forEach(sym => {
-
let descriptor = Object.getOwnPropertyDescriptor(source, sym);
-
if (descriptor.enumerable) {
-
descriptors[sym] = descriptor;
-
-
-
Object.defineProperties(target, descriptors);
-
-
-
-
-
var copy = completeAssign({}, obj);
-
-
Polyfill
此polyfill不支持 symbol 属性,因为ES5 中根本没有 symbol :
-
if (typeof Object.assign != 'function') {
-
-
Object.defineProperty(Object, "assign", {
-
value: functionassign(target, varArgs){
-
-
-
throw new TypeError('Cannot convert undefined or null to object');
-
-
-
-
-
for (var index = 1; index < arguments.length; index++) {
-
var nextSource = arguments[index];
-
-
if (nextSource != null) {
-
for (var nextKey in nextSource) {
-
-
if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
-
to[nextKey] = nextSource[nextKey];
-
-
-
-
-
-
-
-
-
-