- 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