前言
今天我们来看看另外一个面试高频手写题:new,我们同样先来搞清楚new关键字的原理,然后我们来自己手撸一个简单版本
前置
同样首先我们在手写代码之前,我们应该要搞清楚几个问题:
- new关键字的原理是什么?
- new关键字有什么用?
- 实现一个new关键字分为哪几步?
OK,明确目的之后,我们来开始!
new的原理
我们先来看一下MDN中对于new的描述:new运算符创建一个用户定义的对象类型的实例或具有构造函数的内置对象的实例
是不是感觉还是很模糊,没事儿(官方定义一般都长这样),那我们来使用我们的理解来解读一下:
new主要作用就是执行一个构造函数,然后返回一个实例对象,在这个过程中来确定是否可以接收参数的传递
是不是感觉还是不懂?没关系,我们继续来看,文字看不懂,我们来看两个代码实例:
使用new的情况:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const car1 = new Car('USA', 'TSL', 1993)
console.log(car1, car1.year)
// { make: 'USA', model: 'TSL', year: 1993 } 1993
复制代码
不使用new的情况:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const car1 = Car('USA', 'TSL', 1993)
console.log(car1, car1.year)
// undefined Cannot read property 'year' of undefined
复制代码
这个结果没有疑问吧?那我们可以看出car1是由构造函数Car生成的一个实例对象,那我们经过对比这两个例子是不是可以简单得出new在当中所做一些事情:
- 首先创建一个新对象
- 然后将构造函数的作用域赋给这个新对象(this指向新对象)
- 执行构造函数内部的代码(在这个例子里面就是给新对象添加属性)
- 最后返回这个新对象
new是干啥的这下知道了把~
另外的情况
通过上面的解析,我们知道了new最后是返回一个对象,那现在假如有这么一种情况呢?我们来看代码:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
return {boss: '马斯克'}
}
const car1 = new Car('USA', 'TSL', 1993)
console.log(car1, car1.year, car1.boss)
// { boss: '马斯克' } undefined '马斯克'
复制代码
我们从这段代码中我们可以发现,如果构造函数中最后return返回了一个对象,那么通过new之后会直接返回这个新对象,而不是返回new生成的this对象
那假如return最后返回的不是一个对象呢?我们也来看一下代码:
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
return '马斯克'
}
const car1 = new Car('USA', 'TSL', 1993)
console.log(car1, car1.year)
// { make: 'USA', model: 'TSL', year: 1993 } 1993
复制代码
我们发现如果return返回的不是一个对象,那么最后的结果还是又会返回new新生成的对象
那我们是不是可以得出一个结论:new执行之后总是会返回一个对象,要么是构造函数的实例对象,要么是return之后返回的对象
实现new
OK,经过上面的探索,我们已经基本知道了new是怎么运作的了,那接下来我们就根据这个过程来完成一个最基本的new,我们直接上代码:
//模拟new
const createNew = (Con, ...args) => {
//1、创建一个新的空对象
const obj = {}
//2、把this绑定到空对象
//使空对象的__proto__指向构造函数的原型
obj.__proto__ = Con.prototype
//3、执行构造函数,为空对象添加属性
let result = Con.apply(obj, args)
//4、判断构造函数的返回值是不是对象,如果是,则返回构造函数的返回值,如果不是,则返回创建的对象
return result instanceof Object ? result : obj
}
// 测试
function Car(make, model, year) {
this.make = make;
this.model = model;
this.year = year;
}
const car1 = createNew(Car, 'USA', 'TSL', 1993)
console.log(car1, car1.year)
// { make: 'USA', model: 'TSL', year: 1993 } 1993
复制代码
咋样,经过这段代码测试,我们发现是不是和我们上面分析的过程是不谋而合的?那么现在再要你手写一个new,你会了吗?
文末
欢迎关注「前端光影」公众号,公众号都是以系统专题模块的形式来展示的,这样看起来就会比较方便,系统,让我们一起持续学习各种前端知识,加油