js模拟实现new操作符

2021-02-02  本文已影响0人  VivaLaVida_692c
/**
 * 模拟实现new操作符
 * @param {Function} ctor [构造函数]
 */

export const newOperator = (ctor) => {
    if(typeof ctor !== "function") {
        throw new Error("the first params of newOperator must be a func")
    }
    //ES6 new.target是指向构造函数
    newOperator.target = ctor;
    //创建一个全新的对象
    //并且执行 __proto__ 链接,通过new创建的每个对象将最终被 __proto__ 链接到构造函数的 prototype 对象上
    const newObj = Object.create(ctor.prototype);
    //除去 ctor 构造函数的其余参数
    const argsArr = [].slice.call(arguments, 1);
    //生成的新对象会绑定到函数调用的this,也就是this的指向是实例对象
    const ctorReturnResult = ctor.apply(newObj, argsArr);

    const isObject = typeof ctorReturnResult === "object" && ctorReturnResult !== null;
    const isFunction = typeof ctorReturnResult === 'function';

    if(isObject || isFunction) {
        return ctorReturnResult;
    }

    return newObj;
}

以下例子模拟

function Student(name, age){
    this.name = name;
    this.age = age;
    // this.doSth();
    // return Error();
}
Student.prototype.doSth = function() {
    console.log(this.name);
};
var student1 = newOperator(Student, '若', 18);
var student2 = newOperator(Student, '川', 18);
// var student1 = new Student('若');
// var student2 = new Student('川');
console.log(student1, student1.doSth()); // {name: '若'} '若'
console.log(student2, student2.doSth()); // {name: '川'} '川'

student1.__proto__ === Student.prototype; // true
student2.__proto__ === Student.prototype; // true
// __proto__ 是浏览器实现的查看原型方案。
// 用ES5 则是:
Object.getPrototypeOf(student1) === Student.prototype; // true
Object.getPrototypeOf(student2) === Student.prototype; // true
上一篇下一篇

猜你喜欢

热点阅读