New
new
操作符在 JavaScript 中用于创建一个由构造函数定义的对象实例。它的内部具体执行过程可以分为以下几步:
new
的执行过程
假设我们有如下构造函数:
function Person(name) {
this.name = name;
}
执行 const person = new Person('Alice');
时,new
操作符具体执行了以下步骤:
1. 创建一个空对象
- 创建一个新对象,称为
obj
。 - 这个对象的内部
[[Prototype]]
指针会被设置为构造函数的prototype
属性。
let obj = {}; // 创建一个空对象
obj.__proto__ = Person.prototype; // 设置原型链
2. 绑定 this
- 将新创建的对象
obj
绑定到构造函数的this
上,并执行构造函数代码。
let result = Person.call(obj, 'Alice'); // 将 `this` 指向 `obj`,并传入参数
3. 返回对象
- 如果构造函数返回了一个非原始类型的对象(如对象或数组),则返回该对象。
- 如果构造函数返回的是一个原始值(如字符串、数字、布尔值),或者没有显式返回值,则返回新创建的对象
obj
。
return typeof result === 'object' && result !== null ? result : obj;
完整模拟实现
以下是 new
操作符的一个简化实现:
function myNew(Constructor, ...args) {
// 1. 创建一个空对象,并将其原型指向构造函数的 prototype
const obj = Object.create(Constructor.prototype);
// 2. 执行构造函数,将 `this` 绑定到新对象
const result = Constructor.apply(obj, args);
// 3. 返回结果
return typeof result === 'object' && result !== null ? result : obj;
}
使用 myNew
实现 new
:
function Person(name) {
this.name = name;
}
const person = myNew(Person, 'Alice');
console.log(person.name); // 输出: Alice
new
的作用总结
- 创建一个新对象。
- 将该对象的原型设置为构造函数的
prototype
。 - 执行构造函数,并将新对象作为
this
。 - 根据构造函数的返回值,决定返回的是显式返回的对象还是新创建的对象。
注意事项
原型链继承:
- 新对象的
__proto__
指向构造函数的prototype
。 - 这使得新对象可以访问构造函数原型上的方法和属性。
返回值影响:
- 如果构造函数显式返回一个对象,
new
操作符会忽略新创建的对象,返回该对象。 - 如果返回的是原始值,
new
仍会返回新创建的对象。
构造函数的调用:
- 构造函数是普通函数,但如果不使用
new
调用,this
将指向全局对象(在严格模式下为undefined
),导致逻辑错误。