ES6: Detailed explanation of Object.assign method
- 1 Introduction
- 2. Grammar
- 3. Basic usage
- 4. Advanced usage
- 5. Precautions
- 6. Compatibility
- 7. Comparison with $.extend()
1 Introduction
First understand what Object.assign() is. Let's take a look at how the official ES6 documentation introduces it?
The Object.assign() method is used to copy the values of all enumerable properties from one or more source objects to a target object. It will return the target object.
Note: The Object.assign() method requires at least two objects as parameters, the first parameter is the target object, and the following parameters are the source objects.
2. Grammar
grammar:
Object.assign(target, ...sources)
Parameters:
target
—> target object
source
—> source object
Return value: target
, the target object
3. Basic usage
3.1 The target object and the source object have no attribute with the same name
var target = {
name: '张三', age: 18 }
var source = {
money: '10000' }
var result = Object.assign(target, source)
console.log(result)
console.log(target);
The running results are as follows:
we can see that the state attribute on the source is merged into the target object. If you just want to combine the attributes of two or more objects without changing the attributes of the original objects, you can use an empty object as the target object. Like this:
var target = {
name: '张三', age: 18 }
var source = {
money: '10000' }
var result = Object.assign({
}, target, source)
console.log(result);
The result of the operation is as follows:
3.2 The target object and the source object have attributes with the same name
var target = {
name: '张三', age: 18 }
var source = {
money: '10000', age: 28 }
var result = Object.assign(target, source)
console.log(target)
The running results are as follows:
You can see that if there is an attribute with the same name, the later attribute value will overwrite the previous attribute value.
3.3 There are multiple source objects
var target = {
name: '张三', age: 18 }
var source1 = {
money: '10000', age: 28 }
var source2 = {
mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target)
The running results are as follows:
It can be seen that the situation of multiple source objects is the same as that of one source object. Attributes without the same name will be directly copied to the target object, and the attribute value after the attribute with the same name will overwrite the previous attribute value with the same name.
3.4 Other situations
3.4.1 When there is only one parameter, Object.assign will directly return the parameter
var obj = {
a: 1 }
console.log(Object.assign(obj))
console.log(Object.assign(obj) === obj);
The result of the operation is as follows:
3.4.2 If the parameter is not an object, it will be converted into an object first, and then returned
typeof Object.assign(2) // object
3.4.3 Undefined and null appear
Since undefined and null cannot be converted into objects, if they are used as parameters, an error will be reported.
Object.assign(undefined)
Object.assign(null)
The result of the operation is as follows:
Note: If a non-object parameter appears in place of the source object (i.e. not the first parameter), then the processing rules will be different. First of all, these parameters will be converted into objects, and will be skipped if they cannot be converted into objects. This means that if undefined and null are not in the first parameter, no error will be reported.
let obj = {
a: 1
}
Object.assign(obj, undefined) === obj // true
Object.assign(obj, null) === obj // true
3.4.4 Values of other types
Values of other types (i.e. numeric, string, boolean) are not included in the first parameter without error. However, other values will have no effect except that the string will be assigned to the target object in the form of an array.
var v1 = 'abc'
var v2 = true
var v3 = 10
var obj = Object.assign({
}, v1, v2, v3)
console.log(obj);
The result of the operation is as follows:
In the above code, v1, v2, and v3 are strings, boolean values, and numeric values respectively. As a result, only strings are merged into the target object (in the form of a character array), and numeric values and boolean values are ignored. This is because only string wrapper objects yield enum properties.
console.log(Object(true))
console.log(Object(10))
console.log(Object('abc'));
The running results are as follows:
In the above code, Boolean values, numeric values, and strings are respectively converted into corresponding packaging objects. You can see that their original values are all on the internal property [[PrimitiveValue]] of the packaging object. This property will not Copied by Object.assign(). Only wrapping of strings produces enumerable literal properties, and those properties are copied.
The properties copied by Object.assign are limited, only the own properties of the source object are copied (inherited properties are not copied), and non-enumerable properties (enumerable: false) are not copied.
let obj = Object.assign({
b: 'c' },
Object.defineProperty({
}, 'invisible', {
enumerable: false,
value: 'hello world'
})
)
console.log(obj);
The running results are as follows:
In the above code, the object to be copied by Object.assign has only one non-enumerable pair property invisible, and this property has not been copied in.
Properties whose properties are named Symbol values are also copied by Object.assign.
let obj = Object.assign({
b: 'c' }, {
[Symbol('c')]: 'd' })
console.log(obj);
The result of the operation is as follows:
4. Advanced usage
4.1 Add properties to objects
class Point {
constructor(x, y) {
Object.assign(this, {
x, y })
console.log(this)
}
}
const p1 = new Point('12', '23')
console.log(p1);
The result of the operation is as follows:
The above method adds the x attribute and y attribute to the object instance of the Point class through the assign method.
4.2 Add methods to objects
Object.assign(SomeClass.prototype, {
someMethod (argl, arg2) {
...
},
anotherMethod () {
...
},
})
等同于下面的写法
SomeClass.prototype.someMethod = function (argl, arg2) {
...
}
SomeClass.prototype.anotherMethod = function () {
...
}
The above code uses the concise representation of object properties, directly puts the two functions in braces, and then uses the assign method to add them to SomeClass.prototype.
4.3 Cloning objects
function clone (origin) {
return Object.assign({
}, origin)
}
The above code copies the original object into an empty object, and you get a clone of the original object.
However, using this method can only clone the value of the original object itself, not the value it inherits. If you want to keep the inheritance chain, you can use the following code.
function clone (origin) {
let originProto = Object.getPrototypeOf(origin)
return Object.assign(Object.create(originProto), origin)
}
4.4 Merging Multiple Objects
- Merge multiple objects into one object
const merge = (target, ...sources) => Object.assign(target, ...sources);
- If you want to return a new object after merging, you can rewrite the above function to merge an empty object.
const merge = (...sources) => Object.assign({
}, ...sources);
4.4 Specifying default values for properties
const DEFAULTS = {
logLevel: 0,
outputForrnat: 'html'
}
function processContent (options) {
options = Object.assign({
}, DEFAULTS, options)
console.log(options)
}
In the above code, the DEFAULTS object is the default value, and the options object is the parameter provided by the user.
The Object.assign method merges DEFAULTS and options into a new object. If both have properties with the same name, the property value of options will override the property value of DEFAULTS.
Note: Due to the deep copy problem,
the values of all properties of the DEFAULTS object and the options object can only be simple types, and cannot point to another object, otherwise the property of the DEFAULTS object will not work.
const DEFAULTS = {
url: {
host: 'example.corn',
port: 7070
}
}
processContent ( {
url: {
port : 8000} } )
//{
// url: {port: 8000)
//}
The original intention of the above code is to change url.port to 8000, while url.host remains unchanged. The actual result is that options.url overrides DEFAULTS.url, so url.host no longer exists.
5. Precautions
1. The Object.assign method will only copy the enumerable attributes of the source object itself to the target object. Inherited attributes and non-enumerable attributes cannot be copied;
2. For deep copying, other methods need to be used, because Object.assign() copies attribute values. If the attribute value of the source object is a reference to an object, then it only points to that reference;
3. The target audience itself will change;
4. Abnormalities will interrupt subsequent copy tasks;
5. Object.assign can be used to process arrays, but it will treat arrays as objects.
let obj = Object.assign([1, 2, 3], [4, 5])
console.log(obj); // [4, 5, 3]
In the above code, Object.assign treats the array as an object with attribute names 0, 1, and 2, so attribute 0 of the target array overrides attribute 1 of 0.
6. Compatibility
Currently IE browser is not compatible with Object.assign(), if you need to be compatible with IE, it is best not to use this method directly.
7. Comparison with $.extend()
var target = {
name: '张三', age: 18 }
var source1 = {
state: 'single', age: 22 }
var source2 = {
mood: 'happy', age: 25 }
var result = Object.assign(target, source1, source2)
console.log(target, 'assign')
var targetObj = {
name: '张三', age: 18 }
var sourceObj1 = {
state: 'single', age: 22 }
var sourceObj2 = {
mood: 'happy', age: 25 }
var result = $.extend(targetObj, sourceObj1, sourceObj2)
console.log(targetObj, 'extend')
It can be seen that the results obtained by both are the same.