ES6: Detailed explanation of Object.assign method

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:
insert image description here
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:
insert image description here

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: insert image description here
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:
insert image description here
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:
insert image description here

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:

insert image description here
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:

insert image description here
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:
insert image description here
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:
insert image description here
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:
insert image description here

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:

insert image description here
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.

Guess you like

Origin blog.csdn.net/DZQ1223/article/details/131825042