object.create 的核心是创建空对象并将其 [[prototype]] 指向指定对象,不调用构造函数、不拷贝属性,仅建立原型链;手动实现需用临时构造函数绑定 prototype,并处理 null 原型及属性描述符。

手动实现 Object.create 的核心是:创建一个空对象,并将其 [[Prototype]](即内部原型)指向指定对象。它不调用构造函数,也不拷贝属性,只是建立原型链连接。
手动实现 Object.create 的关键步骤
要模拟原生行为,需满足两点:返回新对象、设置其原型。最简洁可靠的写法是利用临时构造函数:
- 定义一个空的构造函数
F - 将
F.prototype指向传入的原型对象proto - 用
new F()创建实例,该实例的__proto__就是proto - 处理边界情况:当
proto为null时,返回无原型的对象(ES6 允许)
function myCreate(proto, propertiesObject = null) {
if (proto !== null && typeof proto !== 'object') {
throw new TypeError('Object prototype may only be an Object or null');
}
if (proto === null) {
return Object.setPrototypeOf({}, null);
}
function F() {}
F.prototype = proto;
const obj = new F();
if (propertiesObject != null) {
Object.defineProperties(obj, propertiesObject);
}
return obj;
}
它在原型式继承中如何起作用
Object.create 是原型式继承的基石操作——它让一个对象直接“继承”另一个对象的属性和方法,无需类或构造函数参与。
- 子对象通过
__proto__链接到父对象,读取属性时自动向上查找(委托) - 修改子对象自身属性不影响父对象;只有读取未定义属性时才触发原型查找
- 适合构建轻量、动态的对象关系,比如配置对象继承默认配置、组件共享行为等
例如:
const defaults = { theme: 'light', fontSize: 14 };
const userConfig = myCreate(defaults, {
lang: { value: 'zh-CN', writable: true }
});
console.log(userConfig.theme); // 'light' ← 来自 defaults
console.log(userConfig.lang); // 'zh-CN' ← 自身属性
userConfig.theme = 'dark';
console.log(defaults.theme); // 仍是 'light'
与 new 构造函数方式的本质区别
使用 new Foo() 会执行构造函数、绑定 this、设置 constructor 属性;而 Object.create(proto) 完全跳过执行逻辑,只建立原型链接。
-
Object.create返回的对象,其constructor指向的是原型对象的constructor(可能不是你期望的) - 它更纯粹地表达“我想要这个对象的行为像另一个对象”,而非“我按某个模板实例化一个东西”
- 现代开发中常用于组合模式、行为复用、或配合
class实现 mixin 式扩展
注意事项和兼容性提醒
原生 Object.create 支持第二个参数(属性描述符对象),手动实现时若需完整功能,必须调用 Object.defineProperties 处理。
- 不能用
{ __proto__: proto }替代,因为__proto__是非标准(尽管广泛支持)、且不可枚举、不被推荐 - IE9+ 支持原生
Object.create;低版本需 polyfill,上面的手动实现就是典型 polyfill 写法 - 如果仅需简单继承,且不关心
constructor或属性描述符,甚至可用Object.setPrototypeOf({}, proto)(但性能略差)











