关于javascript:JS-原生方法原理探究七如何实现-Objectassign

42次阅读

共计 1965 个字符,预计需要花费 5 分钟才能阅读完成。

这是 JS 原生办法原理探索系列的第七篇文章。本文会介绍如何实现 Object.assign() 办法。

Object.assign() 的根本用法

要实现 Object.assign(),首先理解它的大略用法:

  • 承受的第一个参数示意指标对象(浅拷贝的后果),如果是 null 或者 undefined,间接报错;如果是对象字面量或者数组,间接应用;如果是根本类型,则装箱为对应的对象。
  • 如果只承受了第一个参数,则将其包装为对象间接返回;如果不止承受了第一个参数,比如说承受了第二,第三 …… 等多个参数,那么这些参数示意源对象,它们的本身可枚举属性会一一增加到指标对象上,属性同名则以靠后的对象为准,进行属性笼罩。
  • 第一个参数往后的参数,如果是 null 或者 undefined,那么间接跳过;其余的状况则尝试找出它们的可枚举属性,但实际上,只有字符串、数组、对象字面量这些类型是具备可枚举属性的。

实现代码

依据下面所讲的思路,实现的代码就是上面这样的:

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
})

须要留神的要点

须要留神的要点如下:

为什么不间接通过 . 给 Object 增加 myAssign 办法?

Object.myAssign() 实际上是 Object 的一个静态方法,然而不要间接通过 . 增加,因为这种形式增加的办法是能够枚举的,而 assign() 办法不可枚举。所以这里应用 Object.defineProperty() 增加,同时设置该办法不可枚举、可读、可配置。

为什么要应用严格模式?

考查参数呈现字符串的状况。上面这两种状况容易了解:

Object.assign({a:1},"cd")     
// 把 "cd" 的可枚举属性 0 和 1 增加到指标对象上,最初失去 {a:1,0:“c”,1:"d"}

Object.assign("cd",{a:1})
// 把 {a:1} 的可枚举属性 a 增加到指标对象上,最初失去 String{“cd”,a:1}

但如果是这种状况:

Object.assign("ab","cd")    
// 报错 Cannot assign to read only property '0' of object '[object String]'

这里尝试把 “cd” 的可枚举属性 0 和 1 增加到指标对象上,但问题是,指标对象 String{“ab”} 也有可枚举属性 0 和 1,而且是只读的,这意味着咱们尝试去批改指标对象的只读属性,所以报错也就很正当了。然而,在非严格模式下,这种行为只会静默失败,为了让它真的抛出谬误,必须申明应用严格模式。

为什么不应用 Reflect.ownKeys(obj)

思考指标对象和源对象都是数组的状况,应用 Reflect.ownKeys(obj) 的确能够一次性取得 obj 的本身可枚举属性,然而这些属性除了数组索引之外,也蕴含数组长度, 这会导致将源对象的数组长度作为指标对象的数组长度 ,但实际上,两者长度不肯定相等。比方,Objetc.myAssign([1,2,3],[8,9]) 的后果将不是冀望失去的 [8,9,3],而是 [8,9],因为指标对象的长度被笼罩了。

为什么不间接应用 obj.hasOwnProperty(key)

既然不能应用 Reflect.ownKeys(obj),那么就只有先应用 for(let key in obj) 取得 obj 的本身属性 + 原型链属性,再应用 obj.hasOwnProperty(key) 筛选出本身属性了。然而为什么不间接应用 obj.hasOwnProperty(key) 呢?

这是因为,咱们对源对象的状况并不理解。一方面,它可能重写了 hasOwnProperty 办法;另一方面,它可能是基于 Object.create(null) 构建的,这样的对象不会从 Object 原型上继承 hasOwnProperty 办法。所以这里借用 Object 原型的 hasOwnProperty 办法,是最保险的形式。

正文完
 0