现如今的前端面试中,常常会考察候选人的编码能力。不仅会考察基本的数据结构与算法,还会考察javascript基本功,看候选人对js基础的理解和掌握程度。
面试官:请你简单实现一下js的new
要想实现一个东西,必须要懂这个东西是做什么用的,new的基本功能是创建一个实例对象。
js中实现类与对象创建的原理是构造函数和原型,ES6虽然引入了class,但其内部机制仍然没有变。
假如有一个比较简单的构造函数Animal
function Animal (name) {
this.name = name
}
如果我们要创建一个实例对象的话,通常使用new方法构造。实例对象会继承构造函数原型上的属性与方法
const cat = new Animal('cat')
// cat.name 是 cat
懂了new是什么了之后,我们就可以用代码实现他啦~
第一步:我们把new方法挂载到Function构造函数的原型上来进行模拟
Function.prototype.myNew = function () {
}
第二步:new会返回一个实例对象
Function.prototype.myNew = function () {
let obj = {}
return obj
}
第三步:通过new创建的实例对象会继承构造函数的所有属性和方法,我们可以用Object.create方法去复制构造函数的原型,注意:这里的this指向是构造函数本身,复制之后我们就可以return了。
Function.prototype.myNew = function () {
let obj = Object.create(this.prototype)
return obj
}
第四步:new的过程,构造函数里的语句是会被执行的,如this.name = name,会将name赋值给实例对象,所以我们需要执行原有构造函数,并指定this指向为创建的实例对象。
Function.prototype.myNew = function () {
let obj = Object.create(this.prototype)
this.call(obj, ...arguments)
return obj
}
第五步:还需要考虑一些特殊情况,需要区分构造函数执行结果是否为一个引用对象。
举一个简单的例子
function Animal (name) {
this.name = name
return {}
const cat = new Animal('cat')
// cat则为 {}
}
function Animal (name) {
this.name = name
// 当构造函数返回的是一个原始值
return 'abc'
const cat = new Animal('cat')
// cat则为 {name: 'cat'}
}
#### 这里我们通过instance of 来判断函数执行结果是否为一个引用对象,如果是的话则返回该结果,如果不是的话则返回我们创建的obj。
只需注意这两种特殊情况即可,那么我们最终的代码为:
Function.prototype.myNew = function () {
let obj = Object.create(this.prototype)
let result = this.call(obj, ...arguments)
return result instance of Object ? result : obj
}