深入了解JavaScript中的new操作符

开头先用简单的一句话介绍一下new

new 运算符用于创建对象的实例

前言

new操作符在执行过程中会改变this的指向,所以在了解new操作符之前,我们先熟悉一下this。

1
2
3
4
5
function Cat(name, age) {
this.name = name;
this.age = age;
}
console.log(new Cat('miaomiao', 18)); // Cat {name: "miaomiao", age: 18}

我们并没有return任何信息,输出的结果中包含了name与age的信息。这就是this的作用了。
在JavaScript中,如果函数没有return值,则默认return this。上面代码中的this实际为Cat空对象,后两句就相当于给Cat对象添加name和age属性。

new的时候发生了什么

我们先来看看下面这行简单的代码,该代码的作用是通过new操作符生成一个Cat对象的实例。

1
const cat = new Cat();

从表面上看这行代码的主要作用是创建一个Cat对象的实例,并将这个实例值赋予cat变量,cat变量就会包含Cat对象的属性和函数。其实,new操作符做了3件事情,如下代码所示:

1
2
3
4
5
6
// 创建一个空对象
var cat = {};
// 将空对象的__proto__属性指向Cat对象的prototype属性
cat.__proto__ = Cat.prototype;
// 将Cat()函数中的this指向cat变量
Cat.call(cat);

手动实现一个new

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
function objectFactory() {
var obj = new Object(),
// 获取外部传入的构造器
Constructor = [].shift.call(arguments);
// obj的原型指向构造器的prototype
// 因为构造器所有实例对象需要共享的属性和方法,都放在prototype里面
obj.__proto__ = Constructor.prototype;
// 传入的构造器中的this就指向obj对象,这样obj对象就具有了传入的构造器的属性
var ret = Constructor.apply(obj, arguments);
// 确保构造器总是返回一个对象
return typeof ret === 'object' ? ret : obj;
}

// demo
function Cat(name, age) {
this.name = name;
this.age = age;
}
const cat = objectFactory(Cat, '姓名', '18');
console.log(cat); // Cat {name: '姓名', age: '18'}

参考资料:
JavaScript深入之new的模拟实现


深入了解JavaScript中的new操作符
https://xypecho.github.io/2022/11/23/深入了解JavaScript中的new操作符/
作者
很青的青蛙
发布于
2022年11月23日
许可协议