文章目录
Object.create() 是 JavaScript 中用于创建新对象的核心方法之一。它允许你指定新对象的原型([[Prototype]]),是实现原型继承最直接、最纯粹的方式。
一、Object.create() 做了什么事情?
1. 基本语法
Object.create(proto, propertiesObject)
proto:新创建对象的原型对象(可以为null)。propertiesObject(可选):一个对象,其自身可枚举属性作为新对象的属性描述符。
2. 核心功能
- 创建一个新对象。
- 将该对象的内部
[[Prototype]]指向传入的proto。 - 可选地,通过
propertiesObject定义新对象自身的属性(使用属性描述符)。
3. 示例
const parent = {
sayHello() {
console.log('Hello!');
}
};
const child = Object.create(parent, {
name: {
value: 'Alice',
writable: true,
enumerable: true,
configurable: true
}
});
console.log(child.name); // 'Alice'
child.sayHello(); // 'Hello!'(继承自 parent)
console.log(Object.getPrototypeOf(child) === parent); // true
二、手写 Object.create() 的实现思路
核心目标
- 创建一个新对象。
- 设置其原型为
proto。 - 如果提供了
propertiesObject,使用Object.defineProperties定义属性。 - 处理边界情况(如
proto为null或非对象)。
实现步骤
- 类型检查:确保
proto是null或object,否则抛出TypeError。 - 创建对象:可用构造函数 +
new,或直接{}。 - 设置原型:
- 使用
F.prototype = proto+new F(),或 - 使用
Object.setPrototypeOf()。
- 使用
- 定义属性:使用
Object.defineProperties(obj, propertiesObject)。 - 返回对象。
三、手写实现
基础版(不支持 propertiesObject)
function create(proto) {
// 1. 类型检查
if (typeof proto !== 'object' && typeof proto !== 'function' && proto !== null) {
throw new TypeError('Object prototype may only be an Object or null');
}
// 2. 创建一个空构造函数
function F() {}
// 3. 将其 prototype 指向 proto
F.prototype = proto;
// 4. 创建新对象,其 __proto__ 指向 proto
const obj = new F();
// 5. 特殊处理 proto 为 null 的情况
if (proto === null) {
return Object.setPrototypeOf({}, null);
}
return obj;
}
注意:
new F()无法创建[[Prototype]]为null的对象,因为当F.prototype为null时,实例的[[Prototype]]会退回到Object.prototype。
完整版(支持 propertiesObject 和 null 原型)
function create(proto, propertiesObject) {
// 1. 类型检查
if (typeof proto !== 'object' && typeof proto !== 'function' && proto !== null) {
throw new TypeError('Object prototype may only be an Object or null');
}
// 2. 创建新对象
let obj;
if (proto === null) {
obj = Object.setPrototypeOf({}, null);
} else {
function F() {}
F.prototype = proto;
obj = new F();
}
// 3. 如果传入 propertiesObject,定义属性
if (propertiesObject !== undefined) {
Object.defineProperties(obj, propertiesObject);
}
return obj;
}
更现代的实现(推荐)
function create(proto, propertiesObject) {
// 1. 类型检查
if (typeof proto !== 'object' && typeof proto !== 'function' && proto !== null) {
throw new TypeError('Object prototype may only be an Object or null');
}
// 2. 创建空对象
const obj = {};
// 3. 设置原型
Object.setPrototypeOf(obj, proto);
// 4. 定义属性(可选)
if (propertiesObject) {
Object.defineProperties(obj, propertiesObject);
}
return obj;
}
推荐使用此版本:逻辑清晰,兼容
null原型,代码简洁。
四、测试实现
// 测试 1:正常继承
const parent = { greet() { console.log('Hello!'); } };
const child = create(parent);
child.greet(); // 'Hello!'
console.log(Object.getPrototypeOf(child) === parent); // true
// 测试 2:null 原型
const obj = create(null);
console.log(Object.getPrototypeOf(obj)); // null
console.log(obj.toString); // undefined
// 测试 3:带属性定义
const person = create(
{ species: 'Human' },
{
name: {
value: 'Alice',
writable: true,
enumerable: true,
configurable: true
}
}
);
console.log(person.name); // 'Alice'
console.log(person.species); // 'Human'
五、与 new 的区别
| 对比项 | Object.create(proto) | new Constructor() |
|---|---|---|
| 原型设置 | 直接指定原型对象 | 原型来自 Constructor.prototype |
| 构造函数 | 不调用构造函数 | 调用 Constructor 函数 |
| 适用场景 | 纯原型继承、对象字面量继承 | 构造函数模式、类继承 |
使用场景对比
// Object.create 更适合“直接继承一个对象”
const animal = { sleep() { console.log('zzz'); } };
const rabbit = Object.create(animal);
// new 更适合“通过构造函数创建实例”
function Dog(name) { this.name = name; }
Dog.prototype.bark = function() { console.log('Woof!'); };
const dog = new Dog('Rex');
六、总结
Object.create() 做了什么?
- 创建一个新对象。
- 设置其
[[Prototype]]为指定对象(或null)。 - 可选地定义自身属性。
手写实现思路:
- 类型检查:确保
proto合法。 - 创建对象:可用
new F()或{}。 - 设置原型:通过
F.prototype或Object.setPrototypeOf。 - 定义属性:使用
Object.defineProperties。 - 返回对象。
建议
- 优先使用
Object.setPrototypeOf版本,更简洁。 - 解释清楚
null原型的处理。 - 对比
new和Object.create的使用场景。
掌握
Object.create的实现,就掌握了 JavaScript 原型继承的本质。
1697

被折叠的 条评论
为什么被折叠?



