实现 Object.create

手写 Object.create 方法

问题

从零实现 Object.create 方法,创建一个以指定对象为原型的新对象。

解答

基础实现

function objectCreate(proto) {
  // 参数校验:proto 必须是对象或 null
  if (typeof proto !== 'object' && typeof proto !== 'function') {
    throw new TypeError('Object prototype may only be an Object or null')
  }

  // 创建空构造函数
  function F() {}
  // 将构造函数的原型指向传入的对象
  F.prototype = proto
  // 返回新实例,该实例的 __proto__ 指向 proto
  return new F()
}

完整实现(支持属性描述符)

function objectCreate(proto, propertiesObject) {
  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()

  // 处理 null 原型的情况
  if (proto === null) {
    obj.__proto__ = null
  }

  // 如果传入了属性描述符,使用 defineProperties 添加属性
  if (propertiesObject !== undefined) {
    Object.defineProperties(obj, propertiesObject)
  }

  return obj
}

测试

const person = {
  greet() {
    console.log(`Hello, I'm ${this.name}`)
  }
}

// 基础用法
const tom = objectCreate(person)
tom.name = 'Tom'
tom.greet() // Hello, I'm Tom
console.log(Object.getPrototypeOf(tom) === person) // true

// 带属性描述符
const jerry = objectCreate(person, {
  name: {
    value: 'Jerry',
    writable: true,
    enumerable: true
  },
  age: {
    value: 18,
    writable: false
  }
})
jerry.greet() // Hello, I'm Jerry
console.log(jerry.age) // 18

// null 原型(纯净对象)
const dict = objectCreate(null)
console.log(dict.toString) // undefined,没有继承 Object.prototype

关键点

  • 核心原理:借助空构造函数,将其 prototype 指向目标原型,再 new 出实例
  • 参数校验:proto 只能是对象或 null,否则抛出 TypeError
  • null 原型:创建的对象不继承任何属性,适合用作纯净的字典
  • 第二个参数:属性描述符对象,通过 Object.defineProperties 实现
  • {} 的区别:{} 原型是 Object.prototypeObject.create(null) 原型是 null