new 操作符

MDN文档

new 的作用#

一般的构造函数#

看个简单的例子

function Person (name) {
this.name = name;
}
Person.prototype.run = function () {
console.log(this.name + '正在跑步...');
}
const p = new Person('Tom');
console.log(p.name); // Tom
p.run(); // Tom正在跑步...

得到结论:

  • 通过 new 创建的实例可以访问到构造函数中的属性;
  • 通过 new 创建的实例可以访问到构造函数原型链中的属性,即通过 new 将实例与构造函数在原型链上建立了连接。

特殊的构造函数#

一般情况下,构造函数是没有返回值,下面探讨构造函数有返回值的情况:

基本类型#

function Person (name) {
this.name = name;
return 1;
}
Person.prototype.run = function () {
console.log(this.name + '正在跑步...');
}
const p = new Person('Tom');
console.log(p.name); // Tom
p.run(); // Tom正在跑步...

得到结论:

  • 构造函数如果返回基本类型值,那么这个返回值会被忽略

引用类型#

function Person (name) {
this.name = name;
return { name };
}
Person.prototype.run = function () {
console.log(this.name + '正在跑步...');
}
const p = new Person('Tom');
console.log(p); // { name: 'Tom' }
console.log(p.name); // Tom
p.run(); // TypeError: p.run is not a function

得到结论:

  • 构造函数如果返回引用类型值,那么这个返回值会被正常使用

null#

function Person (name) {
this.name = name;
return null;
}
Person.prototype.run = function () {
console.log(this.name + '正在跑步...');
}
const p = new Person('Tom');
console.log(p.name); // Tom
p.run(); // Tom正在跑步...

得到结论:

  • 构造函数如果返回 null,那么这个返回值会被忽略

小结#

new 的作用如下:

  • 通过 new 创建的实例可以访问到构造函数中的属性;
  • 通过 new 创建的实例可以访问到构造函数原型链中的属性,即通过 new 将实例与构造函数在原型链上建立了连接;
  • 当构造函数返回基本类型值或 null 时,可忽略返回值,但是若返回的为引用类型值,则需将其正常返回,且此时通过 new 创建的实例不可访问到构造函数原型链中的属性。

new 的实现#

function newOperator(Con, ...args) {
let obj = {};
Object.setPrototypeOf(obj, Con.prototype); // 相当于 obj.__proto__ = Con.prototype
let result = Con.apply(obj, args);
return result instanceof Object ? result : obj;
}

1、定义函数:接受不定量的参数,第一个参数为构造函数,接下来的参数被构造函数使用;

2、创建空对象 obj

3、通过 setPrototypeOf 将 obj 与构造函数原型建立连接,等同于 obj.__proto__ = Con.prototype

4、将 obj 绑定到构造函数上,并且传入剩余的参数;

5、判断构造函数返回值类型,如果为引用类型就使用构造函数返回的值,否则使用 obj

知乎上有个有意思的文章可以参考阅读下