持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第N天,点击查看活动详情
前言
这是系列第一篇文章,希望从写下这篇文章开始,能够让自己静下心来不断夯实自身基础,写出更多的文章,做更酷的事情
相信接触过JS的同学对于new操作符都已经比较熟悉了,我们曾经写下的很多代码当中或多或少都有类似的代码片段
function SuperType(name) {
this.name = name;
}
SuperType.prototype.getName = function () {
return this.name;
}
const newInstance = new SuperType('陈同学i前端');
那么在这里的new操作符究竟做了些什么呢,让我们一起看看
new操作符应用
- 通过new操作符创建出来的
SuperType实例对象(新对象)可以同时访问到构造函数this以及构造函数原型链中的属性
function SuperType(name) {
this.name = name;
}
SuperType.prototype.getName = function () {
return this.name;
}
const newInstance = new SuperType('陈同学i前端'); // SuperType { name: '陈同学i前端' }
const instance = SuperType('陈同学i前端'); // undefined
console.log(newInstance.name); // 陈同学i前端
console.log(newInstance.getName()); // 陈同学i前端
构造函数中的this指向new SuperType()生成的新对象
通过new SuperType()创建的每个新对象都通过[[Prototype]]关联到SuperType.protytype对象上
但现在构造函数当中并没有返回值,而我们实际的生产开发当中根据实际情况会有对应返回值的设置
- 构造函数返回
原始值不会影响new操作符的产生实例的结果
function SuperType(name) {
this.name = name;
return 100;
// return '100';
}
SuperType.prototype.getName = function () {
return this.name;
}
const newInstance = new SuperType('陈同学i前端'); // SuperType { name: '陈同学i前端' }
const instance = SuperType('陈同学i前端'); // 100
console.log(newInstance.name); // 陈同学i前端
console.log(newInstance.getName()); // 陈同学i前端
在构造函数中增加了原始值作为返回值,new操作符作用生产出来的实例结果并未发现改变
- 构造函数返回
对象将会覆盖new操作符的运算结果,结果等同于直接调用函数的结果
function SuperType(name) {
this.name = name;
return {
name: '陈同学i前端',
age: 18
};
}
SuperType.prototype.getName = function () {
return this.name;
}
const newInstance = new SuperType('陈同学i前端'); // {name: '陈同学i前端',age: 18}
const instance = SuperType('陈同学i前端'); // {name: '陈同学i前端',age: 18}
new的实现
根据上面new的应用,我们可以对new的实现进行分析
- new操作符作用构造函数后会返回一下可操作对象
instance - 可操作对象
instance约等于this,故可以访问所有挂载到this上的属性和方法 - 可操作对象
instance可以访问到构造函数原型上的属性和方法 - 构造函数返回值为
原始值不作处理,返回值为对象直接返回
根据以上的分析便可以进行new的代码编写
function myNew(target, ...args) {
let obj = Object.create(target.prototype); // 创建新的对象并将该对象的原型设置为目标构造函数的原型
let res = target.apply(obj, args); // 调用目标构造函数,将this指向新创建的对象
return res instanceof Object ? res : obj; // 处理返回值
}
实现原理
- 首先myNew函数接受一定数量的参数(n>=1),第一个参数为目标构造函数,后续参数作为目标构造函数入参使用
- 创建一个空对象
obj,由于obj对象需要访问到构造函数原型链上的属性,所以通过Object.create在创建对象时同时设置原型关系,将构造函数原型和obj联系起来 - 通过
Function.apply将构造函数的this指向obj,并传入后续入参 - 判断构造函数返回值是否为
对象,如果为对象则使用构造函数返回的值,否则返回obj
小结
new操作符是前端中比较重要的知识点,其通用实现流程为:
- 创建一个新对象
obj - 对
obj进行原型链构建,即将obj.prototype指向目标构造函数的原型对象 obj绑定到目标构造函数调用的this(fn.apply(obj))构造函数在执行过程中能将this的属性同步到新对象上- 通过new创建的每个对象通过[[Prototype]]链接到目标构造函数的原型对象
- 若目标构造函数没有返回对象类型Object则new操作符作用后会返回新的对象
obj,反之则返回构造函数的返回值