出处:掘金

原作者:金泽宸


为什么要手写 Object.create

在面试、框架源码中,它经常出现:

Object.create(proto) 原理回顾

这个方法的作用是:创建一个新对象,这个对象的 __proto__ 会指向传入的 proto

举例:

const a = Object.create({ x: 1 });
console.log(a.x); // 1(通过原型访问到)
console.log(a.__proto__); // { x: 1 }

最简单实现版本

function myCreate(proto) {
  function F() {}
  F.prototype = proto;
  return new F();
}

测试验证

const parent = { sayHi() { console.log('hi'); } };
const child = myCreate(parent);

console.log(child.__proto__ === parent); // true
child.sayHi(); // hi

补充细节(ES5 语义补全)

原生 Object.create 第二个参数可以传入属性描述符:

Object.create(proto, {
  name: {
    value: 'Mark',
    enumerable: true
  }
});

这是面试高级考法,Polyfill 实现如下:

function myCreate(proto, properties) {
  if (typeof proto !== 'object' && typeof proto !== 'function' || proto === null) {
    throw new TypeError('proto must be object or function and not null');
  }

  function F() {}
  F.prototype = proto;

  const obj = new F();

  if (properties !== undefined) {
    Object.defineProperties(obj, properties);
  }

  return obj;
}

常见易错点

错误理解 正确做法
认为会拷贝属性 ❌ 实际是“链接”原型,不复制
忘记判断 proto 非空对象 应做类型校验
误以为可以用于多继承 JS 不支持真正的多继承,只有多重原型链查找

扩展

自己封装 inherits(child, parent) 工具函数

function inherits(child, parent) {
  child.prototype = Object.create(parent.prototype);
  child.prototype.constructor = child;
}