Object.create的第二个参数可直接定义新对象自身属性的描述符,实现行为继承与状态封装分离;它不调用构造函数,需手动设置原型链和自有属性,适用于需精细控制属性特性的极简继承场景。

Object.create 的第二个参数允许你直接定义新对象的属性描述符,无需先创建对象再用 Object.defineProperty 逐个设置。这在构建极简继承结构时非常高效——既能复用父级原型方法,又能精准控制子实例自身属性的可枚举性、可写性、可配置性等行为。
用第二个参数定义实例自有属性(非继承)
继承通常关注原型链,但 Object.create 的 props 参数定义的是**新对象自身的属性**,不是挂到原型上的。这意味着你可以让子实例拥有带严格描述符的自有状态,同时原型指向父构造函数的 prototype,实现“行为继承 + 状态封装”的分离。
- 语法:Object.create(proto, { propName: descriptor })
- descriptor 可包含 value、writable、enumerable、configurable、get、set
- 若 descriptor 中含 get 或 set,则忽略 value 和 writable
极简继承示例:带只读 id 和私有初始化值
假设父类是 Animal,子类 Dog 需要一个不可修改的 id 和一个默认 name,但 name 应可后续修改:
const Animal = function() {};
Animal.prototype.speak = function() {
return `I'm ${this.name}`;
};
const dog = Object.create(Animal.prototype, {
id: { value: Symbol('dog-1'), writable: false, enumerable: false, configurable: false },
name: { value: 'Buddy', writable: true, enumerable: true, configurable: false }
});
// 此时 dog.__proto__ === Animal.prototype,可调用 speak()
// dog.id 无法被重新赋值,dog.name 可以改
组合原型继承与自有描述符的实用技巧
避免手动重复写 descriptor 模板,可封装工厂函数:
- 提取公共 descriptor 配置(如“仅读不可删”或“可枚举可写”)
- 用 Object.assign 合并多个属性定义,保持声明式风格
- 注意:不能在 props 中定义原型链上已存在的同名访问器属性,否则会覆盖(且无警告)
和 class / extends 的关键区别
class 继承中 this 是由 new 自动绑定并初始化的,而 Object.create 返回的是一个裸对象。因此需确保: 原型链正确(传入 Animal.prototype), 自有属性通过 props 定义(而非在构造函数里 this.xxx = ...), 不依赖 constructor 属性做类型判断(因 Object.create 不触发构造函数)。

















