持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第17天,点击查看活动详情
手写new
一. 通过代码来分析一下new操作符
//创建构造函数
function Person(name, age) {
this.name = name;
this.age = age;
}
//添加方法
Person.prototype.do = function () {
console.log("hhhh");
}
//new操作符调用方法
var p = new Person('lucky',18);
console.log(p)
console.log(p.do)
打印信息
由此可以得出
- new调用返回的是一个对象
- 把函数内部的this指向了这个对象
- 把对象的隐式原型指向了构造函数的显示原型
二.值的注意的点
如果构造函数没有返回值或者返回值是基本类型,则正常返回实例化对象,如果构造函数的返回值是对象类型,则不再返回实例化对象,而是返回该对象类型
function Person(name, age) {
this.name = name;
this.age = age;
//return 1; //返回基本类型会被实例替代
return {obj:'哈哈哈'}; //返回对象类型会替代实例
}
var p = new Person('lucky',18);
console.log(p)
验证如下
-
return 1返回基本类型会被实例替代 -
return {obj:'哈哈哈'}返回对象类型会替代实例
三. 通过以上分析,new运算符的执行过程大致是如下
- 创建对象,开辟内存空间
- 设置原型链
- this指向该内存
- 执行函数中的代码
- 将地址返回
四.知道原理后,我们开始手写new
function Person(name, age) {
this.name = name;
this.age = age;
//return 1; //返回基本类型会被实例替代
return {obj:'哈哈哈'}; //返回对象类型会替代实例
}
Person.prototype.do = function () {
console.log("hhhh");
}
/*
手写new:
1.声明一个对象obj,作为new的返回值(实例化对象)
2.调用构造函数,并且把构造函数的this指向obj
3.修改obj的隐式原型为构造函数的显示原型
4.判断构造函数的返回值类型,如果是基本类型则正常返回obj,否则返回构造函数的返回值
*/
function myNew(FN) {
//声明一个对象obj,作为new的返回值(实例化对象)
var obj = {};
//调用构造函数,并且把构造函数的this指向obj
var FNReturn = FN.apply(obj, Array.from(arguments).slice(1));
//修改obj的隐式原型为构造函数的显示原型
obj.__proto__ = FN.prototype;
//判断类型是object 并且不是null
if (typeof FNReturn === 'object' && FNReturn != 'null') {
return FNReturn;
}
//判断是function
if (typeof FNReturn === 'function') {
return FNReturn;
}
//基本类型值
return obj;
}
//打印验证
var p = myNew(Person, "lucky", "18");
console.log(p)
console.log(p.constructor)
打印验证结果成功
-
return 1返回基本类型会被实例替代,正常返回 -
return {obj:'哈哈哈'}返回对象类型会替代实例
五.总结
除了考虑this指向和原型,最最重要的是构造函数的返回值,严重影响了new操作符的调用。
好了,以上就是本篇文章的分享,感谢阅读!