关于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来创立实例

评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理