function Animal(type) {
    this.type = type;
}
Animal.prototype.say = function() {
    console.log('say')
}

function mockNew() {
    let Constructor = [].shift.call(arguments); // 取出构造函数

    let obj = {}   // new 执行会创建一个新对象

    obj.__proto__ = Constructor.prototype 

    Constructor.apply(obj, arguments)
    return obj
}

let animal = mockNew(Animal, 'dog')

console.log(animal.type) // dog
animal.say() // say




1:arguments是一个类数组,以像是数组的样子取到传入的所有参数,有一个callee属性(值为被调用的方法)利用数组的shift方法拿到了第一项 也就是Animal函数,同时原来的arguments被更改,失去了第一个参数。再后面被apply拿来做参数

2:第4行的Constructor.apply(obj, arguments)
意思是在obj里执行构造函数,并且挨着arguments里剩下的参数

3:[ ]可以等价Array.prototype.shift ,也就是在arguments上执行数组的shift方法的意思

4:最后可以加一个判断,是否为对象再返回

一开始的思想:原本的函数带一个参数,直接用new的时候就要传这个参数的,所以我手写出来的new方法必须提供要执行的构造函数,以及传入的这个参数,通过arguments拿到了构造函数和参数 开始折腾就行了

下面给一个更优雅时髦的写法~

function _new() {
    let target = {}; //创建的新对象
    //第一个参数是构造函数
    let [constructor, ...args] = [...arguments];
    //执行[[原型]]连接;target 是 constructor 的实例
    target.__proto__ = constructor.prototype;
    //执行构造函数,将属性或方法添加到创建的空对象上
    let result = constructor.apply(target, args);
    if (result && (typeof (result) == "object" || typeof (result) == "function")) {
        //如果构造函数执行的结构返回的是一个对象,那么返回这个对象
        return result;
    }
    //如果构造函数返回的不是一个对象,返回创建的新对象
    return target;
}

最近看了慕课 有一种新的写法

function _new(func){
    var obj = object.create(func.prototype)
    var result = func.apply(obj)
    if(typeof result == object){
        return result
    }else{
        return obj
    }
}

主要是object.create方法,参数为new出来的实例的原型,也就是_proto_的指向


绿绿
33 声望3 粉丝