首先回忆一下构造函数的执行过程:
- 初始化作用域链
- 创建一个默认的对象(此对象就是当前类的实例)
- 让上下文中的this指向此对象
- 初始化arguments
- 形参赋值
- 变量提升
- 代码执行
- 在没有返回值的情况下,默认会把创建的实例对象返回。如果return的是基本类型值,返回的还是实例;如果return的是引用类型的值,那么会替代默认返回的实例。 new的功能就是实现了对象的创建,并且使this指向这个对象
function _new(Func) {
//1 创建一个实例对象,并且把Func作为当前对象的的原型链, 也就是此对象是Func的实例
const obj = Object.create(Func.prototype);
//2 获取其他参数
const args = [].slice.call(arguments, 1);
//3 把类当做普通函数执行
const result = Func.apply(obj, args);
//4 看一下是否有返回值,不存在或者返回的是值类型,则默认返回实例,如果返回的是引用数据类型则返回的是自己写的
if (result !== null && /^(object|function)$/.test(typeof result)) {
return result;
}
return obj;
}
有些低版本的浏览器可能不支持 Object.create 我们可以实现一个
Object.create(xxx) 的作用是创建一个空对象,并且把参数作为当前对象的原型链,接下来我们就可以实现这个函数了
// 重写Object.create 创建某个类的空实例
Object.myCreate = function (prototype) {
//1. 创建了一个类
function Func() {}
//2. 改变了该类的原型链
Func.prototype = prototype;
//3. 返回实例
return new Func();
};
function Func(x, y) {
let num = x + y;
this.x = x;
this.y = y;
}
const fn = _new(Func, 1, 2, 3);
const fn2 = new Func(1,2,3)
console.log(fn);
console.log(fn instanceof Func)
console.log(fn2);
console.log(fn2 instanceof Func)