在很多面试中都会遇到这样一道面试题:如何实现一个new?
实现一个new的简单版本,其实就只有三步。话不多说,直接来。
首先我们需要一个构造函数,根据这个构造函数new 一个对象并打印在控制台中来做参考。
function F(){
this.name = '我是一个构造函数';
};
console.log(new F());
在控制台执行代码会输出一个对象
接下来我们用三步实现一个一模一样的对象,每一步我们都打印一下,对比new生成的对象。
第一步:创建一个空对象
const obj = {};
console.log(obj);
第一步执行后我们有了一个{}(对象)还有一个__proto__ (原型),只不过我们的__proto__和new的__proto__明显是不一样的,所以接下来要让它们变成一样的!
第二步:改变空对象的原型链
obj.__proto__ = F.prototype;
console.log(obj);
与new的对比
这一步执行后基本就与new的对象有了同一个外壳了,最后只要把构造函数里面的代码整到obj中,就大功告成了。
obj.proto = F.prototype
对这一句有疑问的话,可以认真再理解一下原型链
第三步:继承构造函数的属性与方法
F.call(obj);
console.log(obj);
与new的对比
到这里我们就完整创造出一个一模一样的对象了。
这里需要知道call都做了啥?
总结一下
function F(){
this.name = '我是一个构造函数';
};
// 实现new的三行代码
const obj = {};
obj.__proto__ = F.prototype;
F.call(obj);
假设F函数有传参数,我们也可以将三行代码写成一个函数,传递一个name参数,这样我们就封装好了一个简单的类似new语法糖的方法。
const createObject = (name) => {
const obj = {};
obj.__proto__ = F.prototype;
F.call(obj,name);
return obj
}
再进一步假设F函数也要作为一个参数传递到方法中
就可以改造成这样
const createObject = (fn,name) => {
const obj = {};
obj.__proto__ = fn.prototype;
fn.call(obj,name);
return obj
}
假设参数不只一个name呢?这个可以思考一下,其实也不难。
new其实也是类似封装的作用,可以让我们快速的生成一个在原型链生态中的对象,没有它js也可以继续存在,我们可以通过自己的封装。
对比java,没有了new 它还能存在吗?所以js只是有面向对象的编程实现,但是它本身并不是一门面向对象的语言。
文中如有纰漏,请在评论中指出。
最近开始准备面试了 预计7月初就开始投简历了
最近会更新一些刷面试的文章
后面面试了也会出一些面经
文章也发布到了掘金
来点个赞啊哈哈