第二话:JS中new操作符的原理
摘要
用最简单易懂的话,解释复杂的问题。
想必各位总是在面试中被面试官问到:
知道JS中new操作符的原理吗,可以简单实现一下吗?
如果你是第一次碰到这种问题,一定满脑子都是问号。new不是操作符吗?我怎么手撕啊。
其实,只需要实现一个方法,方法接受一个构造函数为参数,返回一个实例对象即可。
在实现之前,我们先简单用ES5来实现一个People类:
function Peopple() {
this.name = "John"
}
const people = new Peopple();
console.log(people.name);
1.处理对象的属性
现在,我们希望实现一个方法,接受People方法为参数,返回一个People类的实例对象。
那就先把方法创建出来呗:
function _new (constructor) {
const obj = {};
return obj;
}
我们希望返回的obj能够成为People类的实例,那换句话来说,我们就是希望obj这个对象能够执行一遍People类的构造函数不是吗。
那我们能直接调用People(obj)
吗?
肯定不能,因为People里面的this不是obj啊,那有什么方法能够改变People里的this指向吗?
这不就来了吗,改变对象this指向的方法一共有三个,call, apply, bind。这里我们就用call来改一下People类的this指向呗,让它指向obj。
function _new (constructor) {
const obj = {};
constructor.call(obj);
return obj;
}
const peopple2 = _new(Peopple);
console.log(peopple2.name);
现在我们就可以拿到People类的实例化对象了,并且也能访问对应的属性了。
这里读者可以完善一下,如果带有参数的构造函数应该怎么写。
那写到这里就能让面试官满意了吗????
面试官继续问:
你这种写法,挂载在类原型链上的方法是怎么触发的呢?
2.处理对象的方法
我们知道,类的方法我们一般挂载在原型链上,这样可以保证所有的实例化对象共用一个类方法
function Peopple() {
this.name = "John"
}
Peopple.prototype = {
sayName: function () {
console.log(this.name);
}
}
const people = new Peopple();
people.sayName();
而我们刚才的实现方式,返回的对象,并不能够拿到类原型链上的东西。所以,我们希望创建对象的时候,能够让这个对象的__proto__指向类的prototype。
这不就来了吗。Object.create(XXX.prototype)
不就是干这个的吗。
当然你也可以通过obj.__proto__ = XXX.prototype
这种方式来实现。
现在我们就来重新修改一下我们的代码:
function _new (constructor) {
const obj = Object.create(constructor.prototype);
constructor.call(obj);
return obj;
}
const peopple2 = _new(Peopple);
peopple2.sayName();
写到这里,你擦了擦汗,心想这回应该可以了吧。此时面试官微微一笑:
如果构造函数有返回值时,你实现的这个方法处理的对吗?
3.处理构造函数的返回值
在使用new操作符的时候,有一个需要注意的事情就是,当构造函数的返回值是一个对象的时候,new出来的对象就是返回的对象。
function Peopple() {
this.name = "John";
return {
name: 'Jack'
}
}
const people = new Peopple();
console.log(people.name); // Jack
而我们实现的方法,是直接返回构造好的新对象。所以我们还要处理一下,只需要当传进来的构造函数有返回值时,直接给他返回回去就好了。
function _new (constructor) {
const obj = Object.create(constructor.prototype);
const result = constructor.call(obj);
if (result) return result;
return obj;
}
const peopple2 = _new(Peopple);
console.log(peopple2.name);
Ok,现在我们从,对象的属性、对象的方法、以及构造函数的返回值三个点,手写了一个_new方法。
如果下次有面试官问你:请简单实现一下new的原理。请展示就完了。
最后,希望这篇文章对屏幕前的你有些许的帮助,笔芯♥️。