实现一个bind和new

39 阅读1分钟
首先实现一个bind,需要考虑以下问题:
  1. 传入两个参数,一个是上下文对象、另一个是参数
  2. 返回一个函数,这个函数可能还会传入参数,需要合并
  3. 返回一个匿名函数,意味着,调用的时候this会改变成window,需要闭包来存;
  4. 返回了一个函数,有可能这个函数被当成构造函数使用,就需要注意原型链的指向,当new 一个对象的时候,需要修改原型链,直接创建了一个函数返回,就需要额外指定原型链
  5. new的时候,this指向该对象实例本身,所以判断 this instanceof Fn ,就可以判断出来是否使用new。
代码实现
实现new对象的过程
function myNew(fn,...args){
 if (typeof fn !== "function") {
    console.error("type error");
    return;
  }
  let newObj = Object.create(fn.prototype);
  let res = fn.call(newObj,...args); // 需要执行以下函数,判断是否有返回值,有就返回返回值,没有就返回新对象
  return typeof res ==='object'?res:newObj;
}

function person() {
  this.age =19;
}

function person2() {
  this.age =19;
  return {
    age:1
  }
}
let p1 = myNew(person) // 无返回值的构造函数
let p2 = myNew(person2); // 构造函数不能有返回值
console.log(p1,p2); // person {age:19} {age:1}
实现bind
Function.prototype.myBind = function (context,...args){ // 1
  if (typeof this !== 'function') {
    throw new Error("cannot bind non_function");
  }
  const self =this; // 3
  function Fn(...args1) {
    // 5 this instanceof Fn  
    return self.apply(  this instanceof Fn ? this : context,[...args,...args1])
  }
  Fn.prototype = self.prototype; // 4
  return Fn 
}
function Person(name){
  this.name = name
}
Person.prototype.getName = function(){
  return this.name
}

let BindPerson = Person.bind({age:1}, "xxx");
let bp = new BindPerson();
console.log(bp.getName())