手写Object.create

首先在看这类手写代码的题目的之前,最好是上MDN或者W3C去看看这些代码在原生的JS中是用来的干什么的,它们有哪些参数。这样做有助于我们理解并模拟实现。

Object.create()用于创建一个新的以已有对象为原型的对象。该方法可以接收两个参数。

  • 参数一是作为新对象原型的对象
  • 参数二也是一个对象,该对象会为创建的新对象添加它的所有自有属性(被定义在对象自身而不是对象原型身上的属性),这些属性对应于Object.defineProperties()的第二个参数。(模拟实现的时候也会采用该API)

作为原型的对象如果是基本类型包装对象之外的对象(一般指null和undefined,null是特殊的所以只考虑undefined报错的情况),该方法会抛出错误

有了这些概念,我们首先就能实现一个不那么完善的Object.create()

Object.create2 = function (proto, propertyObject = undefined) {//接收两个参数
    //proto会报错的情况
    if (typeof proto != 'object' && typeof proto != 'function') {
        throw new TypeError('Object prototype may only be an Object or null')
    }

    //利用原型链让新对象原型指向参数对象
    function F() {}
    F.prototype = proto
    const obj = new F()//对象的隐式原型指向它构造函数的显式原型

    //如有第二个参数
    if (propertyObject) {
        Object.defineProperties(obj, propertyObject)
    }
    return obj
}

之所以说不完善是因为还有两个问题我们没有考虑

  • propertyObject为null的时候是需要报错的,因为null身上没有任何属性
  • proto为null的时候会经过第一次筛选。但是以null为原型的对象身上没有任何从Object.prototype中继承的属性和方法,比较特殊。也可以理解为proto为null的时候创建的对象就没有原型对象,这种情况需要单独列出来。

完善之后我们就可以得到这个版本

Object.create2 = function (proto, propertyObject = undefined) {//接收两个参数
    //proto会报错的情况
    if (typeof proto != 'object' && typeof proto != 'function') {
        throw new TypeError('Object prototype may only be an Object or null')
    }
    //propertyObject为null应该报错
    if (propertyObject == null) {
        throw new TypeError('Cannot convert undefined or null to object')
    }

    //利用原型链让新对象原型指向参数对象
    function F() {}
    F.prototype = proto
    const obj = new F()//对象的隐式原型指向它构造函数的显式原型

    //如有第二个参数
    if (propertyObject) {
        Object.defineProperties(obj, propertyObject)
    }

    //支持创建没有原型的对象
    if (proto == null) {
        obj.__proto__ = null
    }
    return obj
}

这里如果不单独将proto为null的情况单独列出来,在执行到代码

const obj = new F()

的时候,因为F的原型被重写为null,ES规范中规定如果一个被创建对象的原型为null的时候,会将这个被创建的对象的原型自动设置为Object.ptototype。而我们给Object.create()传入null参数的本意是希望创建一个没有原型的对象,所以为null的情况需要手动修改obj的原型对象。

详细信息可以查看ES规范13.2.2的第七条中,关于原型对象是null的解决方案。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容