实现一个简单的new方法(超详细)

2,695 阅读2分钟

1. new操作中发生了啥?

在《javaScript模式》中,对于new的过程是这样描述:

  • 创建一个空对象,将它的引用赋给this,继承函数的原型
  • 通过this将属性和方法添加至这个对象
  • 最后返回this指向的新对象,也就是实例 通过书中说明,代码大概是这样:
let Parent = function (name, age) {
    // 1. 创建一个新对象,赋予this,这一步是隐形的
    // let this = {};
    // 2. 给this指向的对象赋予构造属性
    this.name = name;
    this.age = age;
    // 3. 如果没有手动返回对象,则默认返回this指向的这个对象,也是隐形的
    // return this;
}

工作中大家应该看过类似下面的代码,将this赋予一个新的变量,例如that,最后返回这个变量:

// ES5构造函数
function Parent (name, age) {
    let that = this;
    that.name = name;
    that.age = age;
    return that;
};
const child = new Parent('诺安人', 24); // {name = '诺安人', age: 24}

因为this的创建是隐形的,但在工作中为了让构造过程更易可见和维护,所有采用that代替this,最后手动返回that,这也验证了隐形的两个步骤的确存在。

2. 下面实现一个简单的new方法:

function create() {
    // 创建一个空的对象
    let obj = new Object()
    // 将arguments转换成数组,再调用shift方法返回第一个参数,也就是构造函数
    let Con = [].shift.call(arguments)
    // 链接到原型
    obj.__proto__ = Con.prototype
    // 绑定this,执行构造函数(因为apply会自动执行函数,注意现在的argument里面只有传递进来的属性值)
    let result = Con.apply(obj, arguments)
    // 这里进行判断,如果构造函数最后有return操作,那就返回构造函数里面那个对象,没有则返回obj
    // 其实就是对应我们上面所说的那个隐形返回
    return typeof result === 'object' ? result : obj
}
function Person (name, age) {
    this.name = name
    this.age = age
    return this
}
let a = create(Person, '诺安人', 24) // {name = '诺安人', age = 24}

刚开始我不理解 return typeof result === 'object' ? result : obj 这句代码的含义,直到明白了原来有两步隐形操作,后来才恍然大悟。

希望能帮到同样有困惑的童鞋们!