JavaScript - New之后发生了什么?
April 11, 2025
6 min read
#new 操作符的官方定义
根据 MDN 文档,new
运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例。它是 JavaScript 中创建对象和实现面向对象编程的基础机制之一。
#new 操作符的工作原理
当我们使用 new
操作符调用构造函数时,会经历以下四个关键步骤:
- 创建新对象:首先创建一个空对象,作为将要返回的对象实例
- 设置原型链:将这个空对象的原型(
__proto__
)指向构造函数的prototype
属性 - 绑定 this:将构造函数的
this
指向这个新创建的对象,并执行构造函数代码(为新对象添加属性和方法) - 返回新对象:如果构造函数返回一个对象,则该返回值成为整个
new
表达式的结果。否则,返回新创建的对象
#MDN 文档补充说明
在 Class
中 new
操作符必需的,尝试不使用 new
调用一个类将抛出 TypeError
。而对于构造函数,可以通过检查 new.target
属性来判断函数是否通过 new
调用:
检查是否通过new调用JavaScript
function Car(color) {if (!new.target) {// 以函数形式调用return `${color}车`;}// 通过new调用this.color = color;}const a = Car("红"); // a是"红车"const b = new Car("红"); // b是 Car { color: "红" }
此外,不同的内置对象在使用 new
和不使用 new
调用时可能有不同的行为:
Array()
、Error()
和Function()
在被调用时和被构造时表现一致Boolean()
、Number()
和String()
在调用时将参数转换为相应的原始类型,构造时返回包装对象Date()
在调用时返回当前日期的 字符串,相当于new Date().toString()
Symbol()
和BigInt()
只能在不使用new
的情况下调用Proxy
和Map
只能通过new
构造
#手动实现 new 操作符
理解了 new
操作符的工作原理后,我们可以手动实现一个模拟 new
操作符行为的函数:
手动实现new操作符JavaScript
function myNew(Constructor, ...args) {// 1.创建一个新对象const obj = {};// 2.设置原型链Object.setPrototypeOf(obj, Constructor.prototype);// 等价于: obj.__proto__ = Constructor.prototype;// 3.绑定this并执行构造函数const result = Constructor.apply(obj, args);// 4.根据返回值类型决定返回结果return result instanceof Object ? result : obj;}
#使用示例
#基本使用
基本使用示例JavaScript
function Person(name, age) {this.name = name;this.age = age;this.sayHello = function() {console.log(`你好,我是${this.name},今年${this.age}岁`);};}// 使用内置new操作符const p1 = new Person("晴天", 25);// 使用自定义myNew函数const p2 = myNew(Person, "下雨", 30);console.log(p1 instanceof Person); // -> trueconsole.log(p2 instanceof Person); // -> truep1.sayHello(); // -> 你好,我是晴天,今年25岁p2.sayHello(); // -> 你好,我是下雨,今年30岁
#构造函数返回对象的情况
构造函数返回对象JavaScript