new做了什么工作?
-
创建一个新的对象
object
-
将新对象与构建函数通过
原型链
连接起来 -
将构建函数中的
this
绑定到新建的对象obj
上 -
根据构建函数返回类型作判断,如果是
原始值
则被忽略return this
;如果是返回对象
,需要正常处理return 当前的值
流程如下:
-
创建一个空对象
-
将新对象的 proto 指向为
Person.prototype
-
将
Person
构造函数的this
设置为新创建的对象,执行 -
构造函数
Person
没有return
语句或者return
的是简单数据类型 忽略,则将该新创建的对象返回return this
如果return
的是复杂的数据类型则返回的是当前return的值
OK!开始行动吧!光有概念没有熟悉过源码可不行,一步步带你写new实例化过程
1、创建一个空对象
let Obj = {}
2、链接空对象的对象原型和构造函数的原型对象
Obj.__proto__ = Constructor.prototype
3、使用apply改变this指向,使this指向创建的空对象并执行构造函数
let result = Constructor.apply(Obj, args);
4、完整手写版本
//自己写一个 new 操作符的函数
function myNew(Constructor, ...args) {
// 判断Constructor参数是否是函数
if (typeof Constructor !== 'function')
return 'Constructor.apply is not a function';
// 1、创建了一个全新的空对象。
let newObject = {};
// 2、将对象原型链接到这个函数的prototype原型对象上,以链接上构造函数的原型链,完成原型的继承。
newObject.__proto__ = Constructor.prototype;
// 此处是把 1 / 2 步结合到一起
// const newObject = Object.create(Constructor.prototype);
// 3、执行构造函数,
// 并将调用者设置为 newObject,这样在执行构造函数时,this就指向 newObject,参数是args
// 构造函数的返回值赋值给 result
let result = Constructor.apply(newObject, args);
// 4. 判断构造函数执行返回的结果是否是 引用数据类型,
// 若是则返回构造函数执行的结果,否则返回创建的对象。
if ((result !== null && typeof result === 'object') || (typeof result === 'function')){
return result;
}
else{
return newObject;
}
//new 操作符执行完毕
};
//测试
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHello = function () {
console.log("hello " + this.name)
}
const person1 = MyNew(Person, 'zzz', 18)
console.log(person1) // Person0 {name: "zzz", age: 18}
person1.sayHello() // 'hello zzz'