🎯 一、为什么要手写 Object.create?
在面试、框架源码中,它经常出现:
- 用于原型继承的核心方法
- 被用在
new实现、寄生组合继承、polyfill 中 - 许多框架如 Vue 早期的继承方案中使用它创建 prototype chain
🔍 二、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 │ ←——(参数)
└─────┬──────┘
↓
┌─────────────────┐
│ obj │
│ __proto__ → proto
└─────────────────┘
❗ 七、面试常见易错点
| 错误理解 | 正确做法 |
|---|---|
| 认为会拷贝属性 | ❌ 实际是“链接”原型,不复制 |
| 忘记判断 proto 非空对象 | 应做类型校验 |
| 误以为可以用于多继承 | JS 不支持真正的多继承,只有多重原型链查找 |
📝 八、扩展
-
自己封装
inherits(child, parent)工具函数function inherits(child, parent) { child.prototype = Object.create(parent.prototype); child.prototype.constructor = child; }