This is the seventh article in a series exploring the principles of JS native methods. This article shows you how to implement the object.assign () method.

Object.assign()Basic usage of

To implement object.assign (), first understand its general usage:

  • The first argument accepted represents the target object (the result of the shallow copy). If null or undefined, an error is reported. If it is an object literal or array, use it directly; If it is a basic type, the corresponding object is boxed.
  • If only the first argument is accepted, it is wrapped as an object and returned directly; If more than the first parameter is accepted, say the second, third… Then these parameters represent the source object, and their own enumerable properties will be added to the target object one by one. The object with the same name of the property will be the next object to override the property.
  • If the parameter after the first parameter is null or undefined, skip it. The rest try to find their enumerable properties, but in reality, only strings, arrays, and object literals have enumerable properties.

So, the code implemented looks like this:

function myAssign(target,... objs){
    if(target === null || target === undefined) {throw new TypeError("can not convert null or undefined to object")}let res = Object(target)
    objs.forEach(obj= > {
        'use strict'
        if(obj ! =null&& obj ! =undefined) {for(let key in obj){
                if(Object.prototype.hasOwnProperty.call(obj,key)){
                    res[key] = obj[key]
                }
            }
        }
    })
    return res
}
Object.defineProperty(Object.'myAssign', {value: myAssign,
    writable: true.configurable: true.enumerable: false
})
Copy the code

Key points to note:

Why don’t you just go through.Add the ObjectmyAssignMethods?

Object.myassign () is actually a static method of Object, but don’t pass. Add, because methods added this way are enumerable, whereas the assign() method is not. So add object.defineProperty () and make the method non-enumerable, readable, and configurable.

Why use strict mode?

Examine the occurrence of strings for arguments. The following two cases are easy to understand:

Object.assign({a:1},"cd")     
{a:1,0: "c ",1:"d"} // Add the enumerable attributes 0 and 1 of "CD" to the target object.

Object.assign("cd", {a:1})
String{" CD ",a:1}; // Add the enumerable property a to the target object, and get String{" CD ",a:1}
Copy the code

But if this is the case:

Object.assign("ab"."cd")    
// Cannot assign to read only property '0' of object '[object String]'
Copy the code

This is an attempt to add the enumerable attributes 0 and 1 of “CD” to the target object, but the problem is that the target object String{” ab “} also has enumerable attributes 0 and 1 and is read-only, which means we are trying to modify the read-only attributes of the target object, so it makes sense to report an error. However, in non-strict mode, this behavior simply fails silently, and in order for it to actually throw an error, strict mode must be declared.

Why not useReflect.ownKeys(obj)?

Using reflect.ownkeys (obj) does get obJ’s own enumerable properties once, considering that both the target object and the source object are arrays. However, these properties also contain the array length in addition to the array index. This causes the source object’s array length to be used as the target object’s array length. They don’t have to be the same length. For example, Objetc. MyAssign ([1,2,3],[8,9]) will not result in the expected [8,9,3], but [8,9], because the length of the target object is overwritten.

Why not just use itobj.hasOwnProperty(key)

OwnKeys (obj) {for(let key in obj) {for(let key in obj) {for(let key in obj); But why not just use obj.hasownProperty (key)?

This is because we don’t know much about the source object. On the one hand, it might override the hasOwnProperty method; On the other hand, it may be built based on Object.create(null), such an Object does not inherit the hasOwnProperty method from the Object prototype. So borrowing the hasOwnProperty method of the Object prototype is the safest approach.