JavaScript 面试题
目录

请解释 new 操作符的执行过程。手动实现一个 new 操作符。

· 约 5 分钟读完 · 第 25 / 507 章

推荐答案

new 操作符的执行过程主要分为以下四个步骤:

  1. 创建一个新的空对象:首先,创建一个全新的空对象,这个对象的类型将是 object。
  2. 将新对象的 __proto__ 属性指向构造函数的 prototype 属性:将新创建的空对象的原型(__proto__ 属性)指向构造函数的原型对象(prototype 属性)。这样新对象就继承了构造函数原型上的属性和方法。
  3. 将构造函数内部的 this 指向新创建的对象,并执行构造函数中的代码:调用构造函数,并将 this 指向新创建的空对象。这样构造函数中的代码就可以通过 this 来操作新创建的对象,初始化对象的属性。
  4. 根据构造函数的返回值确定 new 操作符的返回值:如果构造函数没有显式返回一个对象(返回 null 或基本数据类型),则 new 操作符返回第一步创建的新对象。如果构造函数显式返回一个对象,则 new 操作符返回这个对象。

手动实现一个 myNew 函数:

本题详细解读

new 操作符的作用

new 操作符的主要作用是:

  • 创建对象实例:它通过调用一个构造函数来创建一个新的对象实例。
  • 建立原型链:它将新对象的原型(__proto__)链接到构造函数的原型对象(prototype),从而实现继承。
  • 初始化对象状态:它执行构造函数,允许通过 this 关键字来设置新对象的属性和方法。

new 操作符的执行步骤详解

  1. 创建一个新的空对象:

    • 首先,new 操作符会在内存中分配一块新的空间来存储这个对象。
    • 这个新对象没有任何属性,是一个空对象。
    • 它的类型是 object。
  2. 将新对象的 __proto__ 属性指向构造函数的 prototype 属性:

    • 每个对象都有一个 __proto__ 属性,指向其原型。
    • 每个函数都有一个 prototype 属性,这个属性指向一个对象,该对象会被作为通过 new 创建的实例的原型。
    • 这一步将新创建的空对象的原型链和构造函数的原型链连接起来,实现原型继承。
  3. 将构造函数内部的 this 指向新创建的对象,并执行构造函数中的代码:

    • 构造函数本质上是一个函数,它的 this 指向取决于调用方式。
    • 当通过 new 调用时,this 会被绑定到新创建的空对象。
    • 构造函数内的代码就可以通过 this.xxx = ... 来初始化新对象的属性。
  4. 根据构造函数的返回值确定 new 操作符的返回值:

    • 默认情况下,如果构造函数没有明确返回值,new 操作符会返回新创建的对象实例。
    • 如果构造函数显式返回一个对象或者函数(非 null),那么 new 操作符将返回构造函数返回的这个对象或者函数。
    • 如果构造函数显式返回的是 null 或者基本类型(如 number、string、boolean、undefined、symbol),new 操作符依然返回新创建的对象实例。

手动实现 myNew 函数的详解

  • 类型检查: 首先检查 constructor 是否是一个函数,如果不是则抛出类型错误。
  • 创建对象: 使用 Object.create(constructor.prototype) 创建一个新对象,这个新对象的原型(__proto__)指向 constructor 的原型(prototype)。
  • 执行构造函数: 使用 apply 调用构造函数,将 this 绑定到新创建的对象 obj,并将参数传递给构造函数。
  • 处理返回值: 判断构造函数的返回值是否是一个对象或者函数,如果是则返回构造函数的返回值,否则返回新创建的对象。
  • Object.create() 的作用 Object.create() 方法创建一个新对象,使用现有的对象来提供新创建的对象的__proto__。这里用构造函数的 prototype 作为新对象的原型,实现了原型继承。

通过 myNew 函数,我们手动模拟了 new 操作符的执行过程,更深入地理解了 new 操作符背后的原理。