实现new、apply、call、bind

new方法

  • 创建一个新对象且将其隐式原型__proto__指向构造函数原型
  • 执行构造函数修改this指向
  • 返回该对象
function myNew(fun){
    return (...args)=>{
        let obj = {
            __proto__:fun.prototype
        };
        fun.call(obj,...args);
        return obj; 
    }
}

apply

  • 将要修改this方法的函数绑定到传入的对象上并且执行绑定的函数 、

核心内容

// 为了让所有函数都有该方法,所以需要绑定到Function的原型上
Function.prototype.myApply = function(context){
    context.fn = this; // 为了让函数中的this指向传入的对象,需要让对象来调用该方法
    context.fn(...arguments[1])
    return res;   
}

完整实现

Function.prototype.myApply = function(context){
    // 判断调用者是否为函数
    if(typeof this !=='function'){
        throw new TypeError('not function')
    }

    context = context || window;
    context.fn = this; // 为了让函数中的this指向传入的对象,需要让对象来调用该方法
    let res = null;
    if(arguments[1]){
        res = context.fn(...arguments[1])
    }else{
        res = context.fn();
    }
    //  删除绑定
    delete context.fn;
    return res;   
}

call

  • 与apply的区别就是传参的方式不一样,apply第二个参数是数组,call方法是一个个的传递

核心内容

// 将方法挂载到目标上执行并返回
Function.prototype.mycall = function(context){
    console.log(arguments); // {0:{name:bonly},1:1,2:2}
    console.log(...arguments); // { name: 'bonly' } 1 2 3
    console.log([...arguments].slice(1)); // [1,2,3]
    let args = [...arguments].slice(1);
    context.fn = this;
    context.fn(...args);
}

完整版

// 思路:将要改变this指向的方法挂到目标this上执行并返回
Function.prototype.mycall = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('not funciton')
  }
  context = context || window
  context.fn = this
  let arg = [...arguments].slice(1)
  let result = context.fn(...arg)
  delete context.fn
  return result
} 

bind

  • 与call和apply的不同就是只是修改this指向,并且返回函数等待执行

核心内容

Function.prototype.myBind = function(context){
    context.fn = this;
    return () => {
        let args = [...arguments].slice(1);
        context.fn(...args);
    }
}

完整版

// 思路:类似call,但返回的是函数
Function.prototype.mybind = function (context) {
  if (typeof this !== 'function') {
    throw new TypeError('Error')
  }
  let _this = this
  let arg = [...arguments].slice(1)
  return function F() {
    // 处理函数使用new的情况
    if (this instanceof F) {
      return new _this(...arg, ...arguments)
    } else {
      return _this.apply(context, arg.concat(...arguments))
    }
  }
}

posted @ 2019-12-19 13:39  bonly-ge  阅读(293)  评论(0编辑  收藏  举报