通过自己实现 new 来理解 new

new 关键字的 MDN 解释

new 运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。

从例子简单来一下理解 MDN 所说的意思

// 创建用户定义的对象类型
function Cat(name){
this.face = '🐱'
this.name = 'Lucy'
}
var catLucy = new Cat()

// 具有构造函数的内置对象的实例
var arr = new Array(1,2)

在 MDN 的后面描述里有说到,当代码 new Foo(...)执行时,会发生以下事情:

  1. 一个继承自 Foo.prototype 的新对象被创建。
  2. 使用指定的参数调用构造函数 Foo ,并将 this 绑定到新创建的对象。
  3. 由构造函数返回的对象就是 new 表达式的结果。如果构造函数没有显式返回一个对象,则使用步骤1创建的对象。(一般情况下,构造函数不返回值,但是用户可以选择主动返回对象,来覆盖正常的对象创建步骤)

new 关键字方方解释的版本

自己动手实现一个 new

代码

// 由于 new 是关键字,我们只能将构造函数以参数形式传入
function New() {
    // 声明一个中间对象,该对象为最终返回的实例
    var res = {};
// 取出参数中的第一项, 就是传入的构造函数
    var Constructor = [].shift.call(arguments)
    // 将实例的原型指向构造函数的原型
    res.__proto__ = Constructor.prototype;
    // 通过apply,将构造函数内部的this指向修改为指向res,即为实例对象
    var ret = Constructor.apply(res, arguments);
    // 当构造函数中明确指定了返回对象时,那么new的执行结果就是该返回对象,否则默认返回res就是当前创建的实例对象
    return typeof ret === 'Object'? ret: res
}

⭐️ 这个 [].shift.call(arguments) 会修改原数组,所以在给 apply 传参时,只需将 arguments 直接放到第二个参数的位置

使用示例

function Cat(name){
this.face = '🐱'
this.name = name
}

var catLucy = New(Cat,'Lucy')
console.log(catLucy, catLucy instanceof Cat)

参考链接


JS 的 new 到底是干什么的? JavaScript深入之new的模拟实现 · Issue #13 · mqyqingfeng/Blog · GitHub