Object.assign() of js method

Keywords: Attribute

Original Link: https://www.jianshu.com/p/d5f572dd3776
  • grammar
Object.assign(target,...sources)
  • Basic Usage

The Object.assign method is used for merging objects, copying all enumerable properties of the source object (source) to the target object (target)

const target = { a: 1 };
const source1 = { b: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

Note that if the target object has the same name property as the source object, or if multiple source objects have the same name property, the following property overrides the previous one

const target = { a: 1, b: 1 };
const source1 = { b: 2, c: 2 };
const source2 = { c: 3 };

Object.assign(target, source1, source2);
target // {a:1, b:2, c:3}

If there is only one parameter, Object.assign returns it directly

const obj = {a: 1};
Object.assign(obj) === obj // true

If the parameter is not an object, it is converted to an object and then returned

typeof Object.assign(2) // "object"

Since undefined and null cannot be converted to objects, errors will occur if they are used as parameters

Object.assign(undefined) // Report errors
Object.assign(null) // Report errors

Processing rules differ when non-object parameters appear in the location of the source object (that is, non-first parameters).First, these parameters are converted to objects, and if they cannot be converted to objects, they are skipped.This means that if undefined and null are not the first parameters, no error will be reported

let obj = {a: 1};
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true

Other types of values (i.e., values, strings, and Booleans) are not the first parameter and do not cause errors.However, other values will not have any effect except that the string will be copied into the target object as an array

const v1 = 'abc';
const v2 = true;
const v3 = 10;

const obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

In the code above, v1, v2, and v3 are strings, Boolean values, and values, respectively. As a result, only strings are combined into the target object (in the form of an array of characters), and both values are ignored.This is because only string wrapper objects produce enumerable properties

Object(true) // {[[PrimitiveValue]]: true}
Object(10)  //  {[[PrimitiveValue]]: 10}
Object('abc') // {0: "a", 1: "b", 2: "c", length: 3, [[PrimitiveValue]]: "abc"}

In the code above, Booleans, values, and strings are converted to corresponding wrapper objects, and you can see that their original values are all on the internal property of the wrapper object [[PrimitiveValue]]], which is not copied by Object.assign.String-only wrapper objects produce enumerable, meaningful attributes that are copied

The properties of an Object.assign copy are limited, copying only the attributes of the source object itself (no inheritance attributes) and not the non-enumerable attributes (enumerable: false)

Object.assign({b: 'c'},
  Object.defineProperty({}, 'invisible', {
    enumerable: false,
    value: 'hello'
  })
)
// { b: 'c' }

In the code above, the object that Object.assign copies has only one non-enumerable property invisible, which is not copied in

Attributes named Symbol values are also copied by Object.assign

Object.assign({ a: 'b' }, { [Symbol('c')]: 'd' })
// { a: 'b', Symbol(c): 'd' }
  • Points of Attention

(1) Shallow copy

The Object.assign method implements a shallow copy, not a deep copy.That is, if the value of an attribute of the source object is an object, then the copy of the target object gets a reference to that object

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

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

In the code above, the value of the a property of the source object obj1 is an object, and the copy of Object.assign gets a reference to that object.Any changes to this object will be reflected on the target object

(2) Substitution of attributes with the same name

For such nested objects, once an attribute with the same name is encountered, Object.assign is handled by replacing instead of adding

const target = { a: { b: 'c', d: 'e' } }
const source = { a: { b: 'hello' } }
Object.assign(target, source)
// { a: { b: 'hello' } }

(3) Processing of arrays

Object.assign can be used to handle arrays, but treats arrays as objects

Object.assign([1, 2, 3], [4, 5])
// [4, 5, 3]

In the code above, Object.assign treats arrays as objects with property names 0, 1, and 2, so property 0 of the source array overrides property 0 of the target array.

(4) Processing of value function

Object.assign can only copy values. If the value to be copied is a function of value, it will be evaluated and then copied

const source = {
  get foo() { return 1 }
};
const target = {};

Object.assign(target, source)
// { foo: 1 }

In the code above, the foo property of the source object is an accessor. Object.assign does not copy this accessor, it just gets the value and copies it to the past

  • Common Use

(1) Add attributes to objects

class Point {
  constructor(x, y) {
    Object.assign(this, {x, y});
  }
}

The above method adds x and y attributes to the object instance of the Point class through the Object.assign method.

(2) Adding methods to objects

Object.assign(SomeClass.prototype, {
  someMethod(arg1, arg2) {
    ···
  },
  anotherMethod() {
    ···
  }
});

// Equivalent to the following
SomeClass.prototype.someMethod = function (arg1, arg2) {
  ···
};
SomeClass.prototype.anotherMethod = function () {
  ···
};

(3) Cloning objects

function clone(origin) {
  return Object.assign({}, origin);
}

The code above copies the original object to an empty object and clones the original object.

However, this cloning method can only clone the value of the original object itself, not the inherited value.If you want to maintain the chain of inheritance, you can use the following code

function clone(origin) {
  let originProto = Object.getPrototypeOf(origin);
  return Object.assign(Object.create(originProto), origin);
}

(4) Merging multiple objects

Merge multiple objects into an object

const merge = (target, ...sources) => Object.assign(target, ...sources);

If you want the merge to return a new object, you can override the above function to merge an empty object

const merge = (...sources) => Object.assign({}, ...sources);

(5) Specify default values for attribute values

onst DEFAULTS = {
  logLevel: 0,
  outputFormat: 'html'
};

function processContent(options) {
  options = Object.assign({}, DEFAULTS, options);
  console.log(options);
  // ...
}

In the code above, the DEFAULTS object is the default value, and the options object is a user-supplied parameter.The Object.assign method combines DEFAULTS and options into a new object, and if both have the same name property, the option property value overrides the DEFAULTS property value

Note that due to the problem of shallow copies, the values of all the attributes of the DEFAULTS object and the options object are preferably simple types and do not point to another object.Otherwise, this property of the DEFAULTS object is likely not to work

const DEFAULTS = {
  url: {
    host: 'example.com',
    port: 7070
  },
};

processContent({ url: {port: 8000} })
// {
//   url: {port: 8000}
// }

The intent of the code above is to change url.port to 8000, leaving url.host unchanged.The actual result is options.url overrides DEFAULTS.url, so url.host no longer exists

Posted by Rabioza123 on Mon, 19 Aug 2019 19:29:09 -0700