手撕new()到底做了些什么?

new的实现步骤

要创建 Person 的新实例,必须使用 new 操作符。以这种方式调用构造函数实际上会经历以下 4个步骤:

(1) 创建一个新对象;

var obj = {};

[toc]

(2) 将构造函数的作用域赋给新对象(因此 this 就指向了这个新对象) ;

obj.__proto__ = Base.prototype;

(3) 执行构造函数中的代码(为这个新对象添加属性) ;

Base.call(obj);

(4) 返回新对象(若返回的是基本数据类型则忽略并返回新对象,若返回的是引用类型则正常使用)。

步骤(4)中返回值的不同会有什么结果?

返回基本数据类型

function Car (price) {
this.price = price
return 20
}
let bigCar = new Car(90)
console.log(bigCar.price) // 90

可以看到返回基本数据类型时返回值会被忽略

返回引用数据类型

function Car (price) {
this.price = price
return { km: 200 }
}
let bigCar = new Car(90)
console.log(bigCar.price, bigCar.km) // undefined, 200

可以看到返回引用数据类型会被正常使用

实现一个new

function _new() {
let target = {}; //创建的新对象
//第一个参数是构造函数
let [constructor, ...args] = [...arguments];
//执行[[原型]]连接;target 是 constructor 的实例
target.__proto__ = constructor.prototype;
//执行构造函数,将属性或方法添加到创建的空对象上,用result接收构造函数的返回值
let result = constructor.apply(target, args);
if (result && (typeof (result) == "object" || typeof (result) == "function")) {
//如果构造函数执行的结构返回的引用类型,则返回对象或者函数
return result;
}
//如果构造函数返回的不是一个对象,返回创建的新对象
return target;
}
阅读剩余
THE END