前言
俗话说:面向对象编程工程师,没有对象就
new一个! 在上篇文章中,我们在实现 原型链继承,构造函数继承等方法中,都用到了new关键字去实例化一个对象。那么为什么new FunctionName()就能实现创建一个实例化对象呢?
探索
首先我们尝试下new FunctionName(),看得到的实例化对象都包括哪些内容。
我们借用上一篇文章中的例子:
function Student() {}
Student.prototype.getName = function() {
return this.name;
}
const student1 = new Student();
console.log(student1)
控制台执行结果:
图中能够清晰地看到,new Student();返回了一个新的对象student1, 红色方框里面返回的是student1的__proto__(补充说明:chrome的[[Prototype]]即是__proto__), 从其中的getName方法就是我们绑定到构造函数Student原型上的方法。
所以我们可以得到这样的结论:
new 一个对象的核心包括以下四步:
- 创建一个空对象
- 将空对象的
__proto__指向构造函数的原型 - 将新对象作为构造函数的执行上下文(即
this) - 返回这个新对象
动手实现
经过上面的一番探索分析,我们根据四步法来实现一下:
- 创建一个空对象
const obj = {} - 将空对象的
__proto__指向构造函数的原型
obj.__proto__ = FunctionName.prototype;
- 将新对象作为构造函数的执行上下文(即
this)
FunctionName.call(obj, arguments);
- 返回这个新对象
return obj;
完整代码示例
const MyNew = function(Fn, ...args) {
const obj = {};
obj.__proto__ = Fn.prototype;
Fn.call(obj, args);
return obj;
}
//测试一下
function Student() {}
Student.prototype.getName = function() {
return this.name;
}
// const student1 = new Student();
const student1 = MyNew(Student)
console.log(student1)
执行结果:
不能说一模一样,只能说完全一致!niceeeee!
不过还是有特殊情况没有考虑到,感谢@书生大佬。
特殊情况
- 构造函数的返回值是一个新对象
function Student() {
return {test: 'hahha'}
}
Student.prototype.getName = function() {
return this.name;
}
new Student()
此时 new Student() 会返回构造函数返回的对象,如下:
- 构造函数返回null 当构造函数返回null时,返回的是我们内部构造的新对象,同我们上面的一般情况。
那么我们就来改造下我们的代码:
const MyNew = function(Fn, ...args) {
const ret = Fn();
if(Object.prototype.toString.call(ret) === "[object Object]") return ret;
const obj = {};
obj.__proto__ = Fn.prototype;
Fn.call(obj, args);
return obj;
}
//测试一下
function Student() {}
Student.prototype.getName = function() {
return this.name;
}
// const student1 = new Student();
const student1 = MyNew(Student)
console.log(student1)
测试结果:
构造函数返回null仍然会走原来的逻辑,改造完成!!!
多想一步
我们的MyNew做成了函数的形式,能不能做成类似关键字形式,直接MyNew Student()呢?
经过一番search,发现是我想多了,关键字是在语法层面定义的,js并没有开放出来,贴上思友给出的方法,供大家思考:
你可以自己写个预处理器,定义自己的语法,做完语法分析拿到AST后输出成普通js。当然这样太麻烦了,你也可以直接正则替换,类似宏的处理
具体的方法已经超出了本篇文章的探究范围,这里不做深究。
总结
关于new关键字的实现原理我们基本已经探究清楚了,大家有任何疑问都可以在评论区留言交流哦~
写文不易,大家可以动动手指点个赞,不胜感激!