乐趣区

关于javascript:前端面试手写代码手写实现new运算符

⚠ 准备常识:

  1. 理解原型和原型链
  2. 理解 this 绑定

1 new 运算符简介

MDN 文档:new 运算符 创立一个用户定义的对象类型的实例或具备构造函数的内置对象的实例。

class Person {constructor(name) {this.name = name;}
}
// 创立自定义对象类型的实例
const person = new Person('小明')
// 创立具备构造函数的内置对象的实例
const date = new Date()

new的作用:创建对象的实例

2 new 到底干了什么事

下面说了 new 的作用是创建对象的实例,那么它到底是怎么创立实例的,外部干了哪几件事?

new Person() 为例,当它执行时,会产生以下事件:

  1. 创立一个空的简略 JS 对象

    const obj = {}
  2. 给这个对象增加属性 __proto__,并将该属性链接到构造函数的 原型对象

    obj.__proto__ = Person.prototype
  3. 调用构造函数 Person,并将this 绑定到新创建的对象obj

    Person.apply(obj)
  4. 如果构造函数没有显式返回一个 对象,则返回新创建的对象,即obj

3 模仿实现 new 运算符

如上所述,new运算符就干了这么 4 件事,上面咱们就依据这 4 个步骤用函数来模仿实现new(面试手写代码)

const _new = function(constructor, ...args) {const obj = {}
    obj.__proto__ = constructor.prototype
    const res = constructor.apply(obj, args)
    // 这一步在 "补充" 中会具体解释
    return res instanceof Object ? res : obj
}

代码非常简单,就是依照下面 4 步,一步一步写就能够了

4 补充

  1. ES5提供了 Object.create 办法,该办法能够创立一个对象,并让新对象的 __proto__ 属性指向曾经存在的对象。

    所以咱们能够应用这个办法合并 1、2 两步

    const obj = Object.create(constructor.prototype)
    // 等价于
    const obj = {}
    obj.__proto__ = constructor.prototype
  2. 为什么咱们在 _new 函数最初一句代码是:

    return res instanceof Object ? res : obj

    因为 new 运算符的第 4 步会分以下 3 种状况:

    • 如果构造函数没有显式return(通常状况)

      那么 person 新创建的对象obj

    • 如果构造函数返回的不是一个对象,比方1"abc"

      那么 person 新创建的对象obj

      function Person() {
        ...
        return 1
      }
    • 如果构造函数显式返回了一个对象,比方{}function() {}

      那么 person不是 新创建的对象 obj 了,而是显式 return 的这个对象

      function Person() {
        // 函数也是对象
        return function() {}
      }
  3. 留神,模仿实现的函数 _new 传入的参数只能是构造函数,不能是类

    class Animal {...}
    _new(Animal)
    // 会报错:Class constructor Animal cannot be invoked without 'new'
    // 类只能通过 new 来创立实例
退出移动版