手写实现new功能

155 阅读1分钟

new操作做了什么

在写new之前,我们需要了解new到底做了啥

const fn=function (name,age){
   this.name=name
   this.age=age
}
fn.prototype.say=()=>{
   console.log('你好我是周杰伦')
}
const obj=new fn('周杰伦',38)
console.log(obj)

上面的new对构造函数做了以下工作:

1、返回一个对象

2、将此对象的原型与构造函数的原型链相链接

3、执行构造函数,并且把构造函数的属性都设置到这个对象上(通过this)

手写new功能

下面我们来写一个create函数来模拟new的功能

function create(fn,...args){
  if(!(fn instanceof Function)){
    throw new Error('你传入的参数不是函数')
  }
  let obj={}
  if(fn.prototype){ //箭头函数没有原型链
     obj=Object.create(fn.prototype)
  }else{
     obj.__proto__={constructor:fn}
  }
  //接原型链
  fn.call(obj,...args)//把fn的属性赋给这个对象
  return obj
}
const obj=create(fn,'周杰伦',38)
console.log(obj)

上面的构造函数需要传入构造函数和其他参数,在刚开始会使用fn的原型链创建一个空对象obj,由于传入的构造函数不一定有原型链,(因为有些无聊的人可能会传一个匿名函数,匿名函数没有原型链也不支持this,不过依然可以帮造一个原型出来)

自带new的构造函数

根据上面的特性,还可以自己写一个自带new功能的构造函数

function constructor(name,age){
   const obj=Object.create(constructor.prototype)
   Object.assign(obj,{name:name,age:age})
   return obj
}
constructor.prototype={
   constructor:constructor,
   say(){console.log('我是周杰伦')}
}
const obj=constructor('周杰伦',38)

打一下obj看看

属性都赋值上了,原型链也加上了,应该没啥问题~