在 JavaScript 中,new
关键字用于创建一个用户定义的对象实例。它的执行过程分为以下步骤:
new
关键字的执行过程
- 创建空对象:
创建一个新的空对象,其[[Prototype]]
(即__proto__
)指向构造函数的prototype
属性。 - 绑定
this
:
将构造函数的作用域(this
)绑定到这个新对象。 - 执行构造函数:
执行构造函数内部的代码(通常用于初始化对象属性)。 - 处理返回值:
- 如果构造函数返回一个 对象,则返回该对象。
- 如果构造函数返回 非对象值(如基本类型或
undefined
),则返回新创建的对象。
手动实现 myNew
函数
function myNew(constructor, ...args) {
// 1. 创建空对象,并绑定原型链
const obj = Object.create(constructor.prototype);
// 2. 执行构造函数,绑定 this 到新对象
const result = constructor.apply(obj, args);
// 3. 根据返回值类型决定最终返回结果
return result instanceof Object ? result : obj;
}
分步解析
1. 创建空对象并绑定原型链
- 使用
Object.create(constructor.prototype)
确保新对象的原型链正确指向构造函数的原型。 - 示例:
function Person() {} const obj = Object.create(Person.prototype); console.log(obj.__proto__ === Person.prototype); // true
2. 执行构造函数并绑定 this
- 通过
apply
将构造函数的this
指向新对象,并传递参数。 - 示例:
function Person(name) { this.name = name; } const obj = {}; Person.apply(obj, ["Alice"]); console.log(obj.name); // "Alice"
3. 处理返回值
- 若构造函数返回对象(如
{}
、new Date()
),则直接返回该对象。 - 若返回非对象值(如
42
、"hello"
),则返回新创建的对象。 - 示例:
function A() { return { flag: true }; } function B() { return 42; } const a = myNew(A); // { flag: true } const b = myNew(B); // B 的实例对象(而非 42)
测试用例
// 用例 1:构造函数无返回值
function Animal(name) {
this.name = name;
}
const cat = myNew(Animal, "Tom");
console.log(cat.name); // "Tom"
console.log(cat instanceof Animal); // true
// 用例 2:构造函数返回对象
function Car() {
return { wheels: 4 };
}
const car = myNew(Car);
console.log(car.wheels); // 4
console.log(car instanceof Car); // false(返回的是普通对象)
// 用例 3:构造函数返回基本类型
function NumberWrapper() {
return 42;
}
const num = myNew(NumberWrapper);
console.log(num instanceof NumberWrapper); // true(返回新对象)
与原版 new
的差异
特性 | 原生 new | myNew 实现 |
---|---|---|
原型链绑定 | 自动绑定到构造函数 prototype | 通过 Object.create 手动绑定 |
返回值处理 | 严格区分对象和非对象返回值 | 通过 instanceof Object 判断 |
性能优化 | 引擎内部优化(如隐藏类) | 无优化 |
异常处理 | 构造函数非函数时报错 | 需手动添加类型检查(未实现) |
边界情况处理
1. 构造函数返回 null
null
是对象类型,但result instanceof Object
为false
,因此返回新对象。function NullReturn() { return null; } const obj = myNew(NullReturn); console.log(obj instanceof NullReturn); // true
2. 构造函数为箭头函数
- 箭头函数无
[[Construct]]
内部方法,无法通过new
调用。 - 解决方案:在
myNew
中添加类型检查。function myNew(constructor, ...args) { if (typeof constructor !== "function") { throw new TypeError("构造函数必须是函数"); } // 其余逻辑不变... }
总结
new
的核心机制:原型链绑定、this
绑定、返回值处理。- 手动实现关键点:
- 使用
Object.create
确保原型链正确。 - 通过
apply
调用构造函数并传递参数。 - 根据返回值类型决定最终结果。
- 使用