面试题开始
写在前面,先来两个道面试题,看看你是否答对了
题目一:
function Person(name){
this.name = name
return this.name
}
let p = new Person('chw')
console.log(p) //输出啥
题目二
function Person(name){
this.name = name
return [1,2]
}
let p = new Person('chw')
console.log(p) //输出啥
先自测一下哈,new的过程是以构造函数的返回值为主,还是有其他规则呐,下面是答案解析过程
题目一的p输出是:{name:'chw'}
题目二的p输出是:{age:12,work:'coding'}
那么我们可以得出一个结论就是:如果构造函数返回的是一个引用值,直接返回这个引用值,如果是返回一个基本类型的话,就还是隐式返回一个对象。
模拟实现一个new
第一版
我们先思考一下new的过程中都做了哪些操作,个人认为有以下执行过程
- 先隐式创建一个对象new object()
- 将this指向这个新创建的对象
- 将新创建的对象__proto__ 指向构造函数的prototype,实现继承
- 隐式返回这个新创建的对象 知道了过程做了什么,我们可以很轻松写出代码,我们可以创建一个函数objFactory(),类似于这样传递参数执行 objFactory(Person,a,b),下面是第一版的代码
function objFactory(){
let obj = new Object()
//取出第一个参数,即构造函数,同时shift也会改变argument类数组
let factory = Array.prototype.shift.call(arguments)
//原型链指向
obj.__proto__ = factory.prototype
//立即执行构造函数,传递回去参数
factory.apply(obj,arguments)
return obj
}
//测试
function Person(name){
this.name = name
}
let p = objFactory(Person,'chw')
//p === {name:'chw'}
第二版
以上就是第一版的实现new的过程了,可以还有一开始我们面试题目的结论问题还没解决,我们还需要对构造函数的放回值进行判断,如果是返回一个引用值,那么就直接返回,否则就返回这个隐式对象。那么我们也可以实现第二版的new过程
function objFactory(){
let obj = new Object()
//取出第一个参数,即构造函数,同时shift也会改变argument类数组
let factory = Array.prototype.shift.call(arguments)
//原型链指向
obj.__proto__ = factory.prototype
//立即执行构造函数,改变this指向,传递回去参数
let result = factory.apply(obj,arguments)
return typeof(result) === 'object' ? result : obj
}
//测试
function Person(name){
this.name = name
return {a:1}
}
let p = objFactory(Person,'chw')
//p === {a:1}
至此,new的实现过程已经完结了,有不对的地方欢迎支出。