实现Object.create
手写实现Object.create方法,创建一个新对象并将其原型指向指定对象
问题
Object.create() 是 ES5 中引入的一个方法,用于创建一个新对象,并将这个新对象的原型(__proto__)指向指定的对象。这道题要求我们手动实现这个方法,理解 JavaScript 中原型链的工作原理。
解答
/**
* 手写实现 Object.create
* @param {Object} proto - 新对象的原型对象
* @param {Object} propertiesObject - 可选参数,为新对象定义额外属性
* @returns {Object} 返回新创建的对象
*/
function myCreate(proto, propertiesObject) {
// 参数校验:proto 必须是对象或 null
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object or null');
}
// 创建一个空的构造函数
function F() {}
// 将构造函数的原型指向传入的对象
F.prototype = proto;
// 创建新对象,其原型为 proto
const obj = new F();
// 处理第二个参数:为对象定义属性
if (propertiesObject !== undefined && propertiesObject !== null) {
Object.defineProperties(obj, propertiesObject);
}
return obj;
}
简化版本(只实现功能):
function myCreate(proto) {
// 参数校验
if (typeof proto !== 'object' && typeof proto !== 'function') {
throw new TypeError('Object prototype may only be an Object or null');
}
// 创建空构造函数
function F() {}
// 设置原型
F.prototype = proto;
// 返回新实例
return new F();
}
使用示例
// 示例1:基本使用
const person = {
name: 'Unknown',
sayHello() {
console.log(`Hello, I'm ${this.name}`);
}
};
const student = myCreate(person);
student.name = 'Tom';
student.sayHello(); // 输出: Hello, I'm Tom
console.log(student.__proto__ === person); // true
// 示例2:使用第二个参数定义属性
const parent = {
greet() {
console.log('Hello from parent');
}
};
const child = myCreate(parent, {
age: {
value: 18,
writable: true,
enumerable: true,
configurable: true
},
name: {
value: 'Alice',
writable: false,
enumerable: true
}
});
console.log(child.age); // 18
console.log(child.name); // Alice
child.greet(); // Hello from parent
// 示例3:创建原型为 null 的对象
const pureObject = myCreate(null);
console.log(pureObject.__proto__); // undefined
console.log(Object.getPrototypeOf(pureObject)); // null
// 示例4:原型链验证
const animal = { type: 'animal' };
const dog = myCreate(animal);
dog.breed = 'Husky';
console.log(dog.breed); // Husky (自身属性)
console.log(dog.type); // animal (继承自原型)
console.log(dog.hasOwnProperty('breed')); // true
console.log(dog.hasOwnProperty('type')); // false
关键点
-
原理:利用构造函数和
new操作符,通过设置构造函数的prototype属性来建立原型链关系 -
参数校验:
proto参数必须是对象或 null,否则抛出 TypeError 异常 -
中间构造函数:创建一个临时的空构造函数
F,避免直接修改原有对象 -
原型指向:将构造函数的
prototype指向传入的proto对象,使得新创建的实例能够继承proto的属性和方法 -
第二个参数:使用
Object.defineProperties()处理可选的属性描述符对象,可以精确控制属性的特性(可写、可枚举、可配置等) -
与直接赋值的区别:
Object.create(proto)创建的是一个全新的对象,proto在其原型链上;而直接赋值obj.__proto__ = proto是修改现有对象的原型(不推荐使用) -
应用场景:实现继承、创建纯净对象(
Object.create(null))、对象克隆等
目录