【js面试题】面试官问你new 操作符具体干了什么?你就这样回答

746 阅读3分钟

在 JavaScript 中,new 操作符是实现面向对象编程的重要工具,它用于创建一个构造函数的实例对象。那么,当我们使用 new 操作符时,背后到底发生了哪些事情呢?

一、创建一个空对象

当使用 new 操作符调用一个函数时,首先会创建一个空对象。这个空对象是一个普通的 JavaScript 对象,它将作为即将被构造函数初始化的实例。例如:

function Person(name) {
    // 这里先忽略构造函数内部的操作
}
var person = new Person('John');
// 在执行 new Person('John') 时,第一步就是创建了一个类似 {} 的空对象

二、设置原型链

新创建的空对象的原型(proto)会被设置为构造函数的原型对象(prototype)。这一步非常关键,因为它建立了实例与构造函数之间的原型继承关系,使得实例能够访问构造函数原型上定义的属性和方法。

function Person(name) {
}
Person.prototype.sayHello = function() {
    console.log('Hello');
};
var person = new Person();
console.log(person.__proto__ === Person.prototype); // true
// 现在 person 实例就可以调用 sayHello 方法了,因为它通过原型链找到了 Person.prototype 上的 sayHello
person.sayHello();

三、绑定 this 并执行构造函数

接下来,new 操作符会将构造函数中的 this 关键字绑定到新创建的空对象上,然后执行构造函数。在构造函数内部,可以通过 this 来初始化新对象的属性。

function Person(name) {
    this.name = name;
}
var person = new Person('Alice');
console.log(person.name); // 'Alice'
// 这里 this 被绑定到了新创建的 person 对象上,所以可以通过 this.name 给 person 对象添加 name 属性

四、返回新对象

如果构造函数没有显式地返回一个对象,则 new 操作符会自动返回新创建并初始化后的对象。但如果构造函数显式地返回了一个原始值(如数字、字符串、布尔值等),new 操作符仍然会返回新创建的对象,而忽略构造函数的返回值;只有当构造函数显式返回一个对象时,new 操作符才会返回该对象。

function Person(name) {
    this.name = name;
    return 123; // 这里返回一个数字,但 new 操作符会忽略这个返回值,仍然返回新创建的对象
}
var person = new Person('Bob');
console.log(person.name); // 'Bob'

function AnotherPerson(name) {
    this.name = name;
    return { age: 25 }; // 这里显式返回一个对象,new 操作符会返回这个对象
}
var anotherPerson = new AnotherPerson('Carol');
console.log(anotherPerson.age); // 25

五、总结

综上所述,new 操作符在 JavaScript 中主要完成了四个重要的步骤:创建空对象、设置原型链、绑定 this 并执行构造函数以及根据情况返回新对象。通过这些步骤,new 操作符使得我们能够方便地基于构造函数创建具有特定属性和方法的实例对象,实现了 JavaScript 中的类与实例的概念,是 JavaScript 面向对象编程的基石之一。理解 new 操作符的工作原理对于深入掌握 JavaScript 语言特性、编写高质量的面向对象代码以及理解原型继承机制都有着极为重要的意义。无论是创建自定义对象类型,还是使用内置对象构造函数,都离不开 new 操作符背后的这些机制在默默地发挥作用。