JavaScript new 的模拟实现

255 阅读2分钟

JavaScript new 的模拟实现

一、什么是 new 操作符

使用过 JavaScript 的朋友一定都使用过 new,new 一个实例出来。然而 new 这个语法糖是个什么过程呢?

首先我们看看 new 操作符是怎么回事:

function Person(name, age) {
    this.name = name;
    this.age = age;
}

Person.prototype.code = "007";

let student = new Person("张三", 18);

console.log(student.code); // "007"
console.log(student.name); // "张三"
console.log(student.age); // 18

我们可以看到:

  1. 创建了一个新的实例对象 student
  2. new 出来的实例 student 的 __proto__ 指向了 Person.prototype
  3. 改变了构造函数里的 this 的指向,不在指向 window,而是指向新建的实例 student

嗯,差不多 new 干了这些事。

**就这样完了吗?**我们还需要注意一些细节:

由于构造函数返回的对象就是 new 出来的结果,一般情况下构造函数不返回值,但用户可以选择主动返回对象,当显式返回对象时,就会覆盖掉 new 操作符创建的实例对象,如下:

function Person(name, age) {
    this.name = name;
    this.age = age;
    return {
        money: 100
    }
}

let student = new Person("张三", 18);
console.log(student);

当显示返回对象时,覆盖实例,不是张三,而是 money。

二、模拟实现 new 操作符

根据上面的 new 操作分析,可以得出以下步骤:

  1. 创建一个新的空对象
  2. 将该对象的 __proto__ 指向构造函数的 prototype(可以使用 Object.create(),省略第一步)
  3. 使用 apply 改变构造函数的 this 的指向,使其指向新建的对象
  4. 捕获进行 apply 操作后的返回值,查看执行构造函数后返回的是否是显式对象而不是 undefined
  5. 如果执行构造函数后的返回值是对象,那么返回该对象,否则返回第一步新建的对象
function myNew(constructor, ...args) {
    if (typeof constructor !== "function") 
        return new TypeError(constructor + " is not a constructor");
    let obj = Object.create(constructor.prototype);
    let result = constructor.apply(obj, args);
    return result instanceof Object ? result : obj;
}

喜欢的话记得点个赞再走哦!