重写内置new

157 阅读1分钟

分析 普通函数执行和new函数执行的区别

一 new执行时函数内部会创建一个对象,并将this指向这个对象
二 函数内部this.xxx的操作都会在这个对象上添加属性
三 如果函数的返回值不是一个对象类型,则函数会将这个创建好的对象返回

代码一

function Dog(name) {
    this.name = name;
}
Dog.prototype.bark = function () {
    console.log('wangwang ');
}
Dog.prototype.sayName = function () {
    console.log('my name is ' + this.name);
}
function _new(Ctor, ...params) {
    //创建ctor的实例对象
    let obj = {}
    obj.__proto__ = Ctor.prototype
    //将函数当做普通函数执行,让方法中的this指向实例对象
    let result = Ctor.call(obj, ...params);
    //判断返回值类型,如果返回值不为原始值,则直接返回函数的返回
    if (!result == null && /^(object|function)$/.test(typeof result)) return result
    return obj
}
let tom = _new(Dog, 'tom')
tom.sayName() //my name is tom

优化后的代码

一 检测类型
二 考虑__proto__属性
function _new1(Ctor, ...params) {
    let obj,
        result,
        proto,
        ctorType;
    proto = Ctor.prototype
    ctorType = typeof Ctor
    console.log(ctorType)
    //Symbol 和bigInt 不能new 不是函数,是函数无原型不能new
    if(ctorType == 'symbol' || ctorType == 'bigint'|| ctorType != 'function' || !proto) throw new TypeError(`${Ctor} is not a constuctor`)
    //考虑ie不能用__proto__
    obj = Object.create(Ctor.prototype)
    result = Ctor.call(obj, ...params);
    if (!result == null && /^(object|function)$/.test(typeof result)) return result
    return obj
}
let tom1 = _new1(Dog, 'tom1')
tom1.sayName() //my name is tom1