Explanation of the usage of Object.assign()

Explanation of the usage of Object.assign()

Syntax: Object.assign(target sources) target: target object, sources: source object

Copies the values of all enumerable properties from one or more source objects to the target object. It will return the target object.

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };
const returnedTarget = Object.assign(target, source);

console.log(target); // Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget); // Object { a: 1, b: 4, c: 5 }

Usage example:

  • Copy an object
const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
  • Deep copy problem
    For deep copy, you need to use other methods, because Object.assign() copies property values. If the property value of the source object is a reference to an object, then it only points to that reference.
let obj1 = { a: 0 , b: { c: 0}}; 
let obj2 = Object.assign({}, obj1); 
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} 

obj1.a = 1; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} 
console.log(JSON.stringify(obj2)); // { a: 0, b: { c: 0}} 

obj2.a = 2; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 0}} 
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 0}}
 
obj2.b.c = 3; 
console.log(JSON.stringify(obj1)); // { a: 1, b: { c: 3}} 
console.log(JSON.stringify(obj2)); // { a: 2, b: { c: 3}} 

// Deep copy 
obj1 = { a: 0 , b: { c: 0}}; 
let obj3 = JSON.parse(JSON.stringify(obj1)); 
obj1.a = 4; 
obj1.b.c = 4; 
console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
  • Merge object
const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };

const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // {a: 1, b: 2, c: 3}, note that the target object itself changes.
  • Merge objects with the same properties
const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };

const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // {a: 1, b: 2, c: 3}, note that the property is overridden by other objects with the same property in subsequent parameters
  • Inherited and non enumerated attributes are copied by supplementary courses
const obj = Object.create({foo: 1}, { // foo is an inherited property.
    bar: {
        value: 2  // bar is an enumerable property.
    },
    baz: {
        value: 3,
        enumerable: true  // baz is a self enumerable property.
    }
});

const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }
  • The original type is wrapped as an object
const v1 = "abc";
const v2 = true;
const v3 = 10;
const v4 = Symbol("foo")

const obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// The original type is wrapped and null and undefined are ignored.
// Note that only wrapped objects of strings can have their own enumerable properties.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
  • Copy properties of Symbol type
const o1 = { a: 1 };
const o2 = { [Symbol('foo')]: 2 };

const obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
  • Exceptions break subsequent copies
const target = Object.defineProperty({}, "foo", {
    value: 1,
    writable: false
}); // The foo property of target is read-only.

Object.assign(target, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
// TypeError: "foo" is read-only
// Note that this exception occurs when copying the second property of the second source object.

console.log(target.bar);  // 2. The first source object is copied successfully.
console.log(target.foo2); // 3. The first attribute of the second source object is copied successfully.
console.log(target.foo);  // 1. The read-only attribute cannot be overwritten, so the second attribute copy of the second source object failed.
console.log(target.foo3); // undefined. After the exception, the assign method exits. The third attribute will not be copied.
console.log(target.baz);  // undefined, the third source object will not be copied to.
  • Copy accessor
const obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

let copy = Object.assign({}, obj); 
console.log(copy); // The value of {foo: 1, bar: 2} copy.bar comes from the return value of the getter function of obj.bar

// The following function copies the property descriptors of all its own properties
function completeAssign(target, ...sources) {
  sources.forEach(source => {
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});

    // Object.assign also copies enumerable Symbols by default
    Object.getOwnPropertySymbols(source).forEach(sym => {
      let descriptor = Object.getOwnPropertyDescriptor(source, sym);
      if (descriptor.enumerable) {
        descriptors[sym] = descriptor;
      }
    });
    Object.defineProperties(target, descriptors);
  });
  return target;
}

copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }

Keywords: JSON Attribute Firefox

Added by Gordicron on Sun, 24 Nov 2019 16:21:09 +0200