javaScript基础之new原理

189 阅读2分钟

面试题开始

写在前面,先来两个道面试题,看看你是否答对了

题目一:
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的过程中都做了哪些操作,个人认为有以下执行过程

  1. 先隐式创建一个对象new object()
  2. 将this指向这个新创建的对象
  3. 将新创建的对象__proto__ 指向构造函数的prototype,实现继承
  4. 隐式返回这个新创建的对象 知道了过程做了什么,我们可以很轻松写出代码,我们可以创建一个函数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的实现过程已经完结了,有不对的地方欢迎支出。