一文让你彻底搞懂new操作

436 阅读4分钟

在日常的前端开发中,new操作符的使用极为频繁,尤其是在创建对象实例时。然而,对于new操作符背后的具体执行过程你真的了解吗,不妨看看这一文😀。我会尽量详细的介绍new操作符在JavaScript中的运作机制,并通过实际示例加深理解。

new操作符的核心流程

当你使用new操作符创建一个对象时,JavaScript引擎执行以下四步关键操作:

  1. 创建新对象:首先,JavaScript会创建一个全新的空对象。

  2. 设置原型:新对象的__proto__属性会被设置为构造函数的prototype属性指向的对象。这意味着新对象现在可以访问构造函数原型上定义的所有属性和方法。

  3. 执行构造函数:构造函数随后被调用,此时this关键字指向新创建的对象。构造函数内部对this的任何赋值都将直接作用于新对象。

  4. 返回对象:若构造函数没有返回非原始值(即不是引用类型的值),则返回该新建的对象obj(默认会添加return this)。否则,返回引用类型的值。

示例代码分析

new都干了啥:

function Base() {
    this.id = 'base';
}

Base.prototype.toString = function() {
    return this.id;
};

var obj = new Base();

在执行new Base()时,JavaScript引擎执行了以下操作:

  1. 创建一个空对象obj
  2. obj.__proto__设置为Base.prototype
  3. 执行Base.call(obj),将this指向obj,并初始化id属性。
  4. 默认返回obj

如果你对JavaScript中的prototype__proto__以及constructor属性的概念感到模糊不清,我强烈推荐你先阅读我上一篇文章深入探索JavaScript的原型与原型链 - 掘金 (juejin.cn)

自定义new方法

为了进一步巩固对new操作符的理解,我们可以尝试自己实现一个简易版本的new方法:

// 定义一个名为newMethod的函数,它接受两个参数:构造函数,可变参数args
function newMethod(ctor, ...args) {
    // 使用Object.create()方法创建一个新对象,其原型(__proto__)为构造函数ctor的prototype属性
    // 这意味着新对象将继承ctor.prototype上定义的所有属性和方法
    let obj = Object.create(ctor.prototype);

    // 使用apply()方法调用构造函数ctor,将新创建的对象obj作为this的上下文,并传递args作为参数
    // 这会执行构造函数ctor的代码,初始化obj的属性和状态
    ctor.apply(obj, args);

    // 返回新创建并初始化完成的对象obj
    // 如果构造函数ctor返回了一个对象,那么这个返回值将会被忽略,因为newMethod的返回也是obj
    // 如果构造函数返回的是对象,则使用构造函数执行的结果。否则,返回新创建的对象
    return obj;
}

// 定义一个名为Parent的构造函数,它接受两个参数:name和age
let Parent = function (name, age) {
    // 在构造函数内部,使用this关键字为新创建的对象添加name和age属性
    this.name = name;
    this.age = age;
};

// 为Parent构造函数的prototype属性添加一个名为sayName的方法
// 这个方法会在控制台上输出调用它的对象的name属性
Parent.prototype.sayName = function () {
    console.log(this.name);
};
// 自定义的newMethod函数创建一个Parent构造函数的实例,并将'小张'和10作为参数传递给构造函数
const child = newMethod(Parent, '小张', 10);

// 调用child对象的sayName方法,由于child继承了Parent.prototype上的sayName方法
// 因此它能够正确地输出child对象的name属性,即'小张'
child.sayName(); // 输出: 小张

这里代码展示了如何自定义一个类似于原生new操作符的行为,通过newMethod函数创建并初始化一个对象实例,同时保留了构造函数和原型链的所有特性。

核心

  • 确保新创建对象的原型链正确设置。
  • 执行构造函数时,需将新创建的对象指定为执行上下文(即设置为this),以便构造函数能够准确地作用于该对象,完成必要赋值和初始化任务。

结语

希望本文能够让你对new操作符有更深刻的认识,如果你有任何疑问或需要进一步探讨的话题,请随时留言交流!写作不易还请看官老爷能不吝赐赞👍!你的鼓励是我源源不竭的动力😄。