1、new到底做了什么
new
操作符是一个非常重要的构造函数调用方式,用于创建并初始化一个特定类型的对象实例。当使用new
关键字调用一个函数时,实际上进行了一系列的操作来确保新对象的正确创建和初始化。以下是new
操作符执行的基本步骤:
-
创建新对象: 首先,
new
操作符会在内存中创建一个新的空对象({}),这个对象将作为即将构造出的实例。 -
设置原型链: 新创建的对象的内部[[Prototype]]属性(也称为
__proto__
或通过Object.getPrototypeOf()
访问)会被设置为构造函数的prototype
属性所指向的对象。这样,新对象就能继承构造函数原型上的属性和方法。 -
绑定
this
值: 紧接着,new
操作符会改变执行上下文,使得构造函数内部的this
关键字指向新创建的对象。这意味着,构造函数内部可以通过this
来给新对象添加属性和方法。 -
执行构造函数: 此时,构造函数会被调用,使用步骤3中绑定的
this
值。任何在构造函数中定义的属性和方法都会被添加到新对象上。 -
返回新对象: 如果构造函数没有显式返回一个对象(或者返回一个原始值如数字、字符串或布尔值),那么
new
操作符会自动返回在第一步中创建的新对象。如果构造函数显式返回一个对象,则返回该对象,而不是第一步中创建的新对象。
2、手写new操作符
function myNew(Constructor, ...args) {
// 创建一个新的空对象,其原型指向构造函数的prototype
const instance = Object.create(Constructor.prototype);
// 将构造函数内部的this绑定到新创建的对象instance上
const result = Constructor.apply(instance, args);
// 检查构造函数是否有返回值,如果有并且返回值是一个对象,则返回该对象
// 否则,返回新创建的实例
return typeof result === 'object' && result !== null ? result : instance;
}
举例代码:
// 示例使用
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function() {
console.log(`Hello, my name is ${this.name}, and I am ${this.age} years old.`);
};
const person = myNew(Person, 'Alice', 30);
console.log(person.name); // 输出: Alice
console.log(person.age); // 输出: 30
person.sayHello(); // 输出: Hello, my name is Alice, and I am 30 years old.