手撕JS方法系列:2-重写内置new

需求:

function Dog(name) {
    this.name = name;
}
Dog.prototype.bark = function () {
    console.log('wangwang');
}
Dog.prototype.sayName = function () {
    console.log('my name is ' + this.name);
}
/*
let sanmao = new Dog('小黑');
sanmao.sayName();
sanmao.bark();
*/
function _new() {
    //=>完成你的代码   
}
let sanmao = _new(Dog, '小黑');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 小黑"
console.log(sanmao instanceof Dog); //=>true
复制代码

思路:了解new做了哪些事

  1. 让构造函数中的this指向这个实例对象
  2. this.xxx = xxx 都是给实例对象设置私有属性和方法
  3. 如果构造函数没有return或者返回的是原始值,则把创建的实例对象返回;若返回的是对象,则以自己返回的为主
const _new = function _new(Ctor, ...params) {
    // 1.格式校验:函数 & 有原型对象 & 不是Symbol/BigInt
    if (typeof Ctor !== "function") throw new TypeError(`${Ctor} is not a constructor!`);
    let name = Ctor.name,
        proto = Ctor.prototype,
        obj,
        result;
    if (/^(Symbol|BigInt)$/i.test(name) || !proto) throw new TypeError(`${name} is not a constructor!`);
    
    // 2.创建当前类的一个实例对象
    obj = Object.create(proto);
    
    // 3.把构造函数像普通函数一样执行,但是this需要指向创建的实例对象
    result = Ctor.call(obj, ...params);
    
    // 4.看函数的返回值,如果没有写返回值,或者返回的是原始值,我们默认返回实例对象;
    // 如果返回的是对象,则以自己返回的为主;
    if (result !== null && /^(object|function)$/i.test(typeof result)) return result;
    return obj;
};
let sanmao = _new(Dog, '小黑');
sanmao.bark(); //=>"wangwang"
sanmao.sayName(); //=>"my name is 小黑"
console.log(sanmao instanceof Dog); //=>true
复制代码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享