首先,我们需要先了解下原型链的知识(详解JS原型与原型链(长文详解) - 掘金 (juejin.cn))
new操作符的原理
- 创建一个空对象,将它的引用赋给this,继承函数的原型
- 通过this将属性和方法添加至这个对象
- 最后返回this指向的新对象,也就是实例
大概是这样的:
function _new (name, age) {
// 1. 创建一个新对象,赋予this,这一步是隐形的
let this = {};
// 2. 给this指向的对象赋予构造属性
this.name = name;
this.age = age;
// 3. 如果没有手动返回对象,则默认返回this指向的这个对象,也是隐形的
return this;
}
我们在写的详细一些:
function myNew() {
// 创建一个空的对象
let obj = Object.create();
// 将arguments转换成数组,再调用shift方法返回第一个参数,也就是构造函数
let Con = [].shift.call(arguments);
// 链接到原型
obj.__proto__ = Con.prototype;
// 绑定this,执行构造函数(因为apply会自动执行函数,注意现在的argument里面只有传递进来的属性值)
let result = Con.apply(obj, arguments);
// 这里进行判断,如果构造函数最后有return操作,那就返回构造函数里面的值,判断是否是其他类型的值,否则则返回obj
return typeof result === "object" ? result : obj;
}
测试一下:
function Person (name, age) {
this.name = name
this.age = age
return this
}
let a = myNew(Person, '诺安人', 24)
// {name = '诺安人', age = 24}