new 操作符的实现原理
理解 new 操作符的执行过程并手写实现
问题
JavaScript 中 new 操作符具体做了什么?如何手写实现一个 new 操作符?
解答
new 操作符的作用
new 操作符用于创建一个给定构造函数的实例对象。
function Person(name, age){
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const person1 = new Person('Tom', 20);
console.log(person1); // Person {name: "Tom", age: 20}
person1.sayName(); // 'Tom'
通过 new 创建的实例可以:
- 访问构造函数中的属性
- 访问构造函数原型链中的属性
返回值的处理
构造函数返回原始类型时,返回值会被忽略:
function Test(name) {
this.name = name;
return 1;
}
const t = new Test('xxx');
console.log(t.name); // 'xxx'
构造函数返回对象时,返回值会被正常使用:
function Test(name) {
this.name = name;
return { age: 26 };
}
const t = new Test('xxx');
console.log(t); // { age: 26 }
console.log(t.name); // undefined
执行流程
new 操作符的执行步骤:
- 创建一个新的空对象
- 将新对象的原型指向构造函数的 prototype
- 执行构造函数,将 this 绑定到新对象上
- 根据构造函数返回值判断:如果是对象则返回该对象,否则返回新创建的对象
手写实现
function mynew(Func, ...args) {
// 1.创建一个新对象
const obj = {};
// 2.新对象原型指向构造函数原型对象
obj.__proto__ = Func.prototype;
// 3.将构造函数的 this 指向新对象
let result = Func.apply(obj, args);
// 4.根据返回值判断
return result instanceof Object ? result : obj;
}
测试代码:
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayName = function() {
console.log(this.name);
}
const person1 = mynew(Person, 'Tom', 20);
console.log(person1); // Person {name: "Tom", age: 20}
person1.sayName(); // 'Tom'
关键点
- new 操作符会创建一个新对象,并将其原型指向构造函数的 prototype
- 构造函数内的 this 会被绑定到新创建的对象上
- 如果构造函数返回对象,则使用该返回值;返回原始类型则忽略
- 实现 new 的核心是原型链连接和 this 绑定
目录