• javascript的call、apply、bind的实现


    Function.prototype具有三个方法:call/apply/bind 每一个函数都是Function内置的实例,所以都可以使用这个三个方法
    作用:三个方法都是强制改变函数中的this指向,语法上有点差异,对箭头函数无效

    call和apply调用语法:
    函数.call(context,params1,params2,…)
    函数.apply(context,[params1,params2,…])

    Function.prototype.call()
    call() 方法使用一个指定的 this 值和单独给出的一个或多个参数来调用一个函数。
    函数.call调用作用是基于__proto__找到Function.prototype.call方法
    然后把找到的call方法执行过程中,把this执行改为context了,也帮我们把函数执行了,也把参数传递给调用的函数了
    备注:该方法的语法和作用与 apply() 方法类似,只有一个区别,就是 call() 方法接受的是一个参数列表,而 apply() 方法接受的是一个包含多个参数的数组。

    Function.prototype.apply()
    apply() 方法调用一个具有给定 this 值的函数,以及以一个数组(或一个类数组对象)的形式提供的参数。
    备注: 虽然这个函数的语法与 call() 几乎相同,但根本区别在于,call() 接受一个参数列表,而 apply() 接受一个参数的单数组。

    Function.prototype.bind()
    bind() 方法创建一个新的函数,在 bind() 被调用时,这个新函数的 this 被指定为 bind() 的第一个参数,而其余参数将作为新函数的参数,供调用时使用

    call方法实现

    call实现—使用eval函数实现

    Function.prototype.call= function (ob) {
      // 如果不指定为this指向 默认window
      ob = ob || window;
    
      //把调用函数在oj里面新添加属性fn存一份
      ob.fn = this;
    
      //处理多个参数问题 排除第一个ob参数 从下标1开始获取剩余参数
      const args = [];
      for (let i = 1; i < arguments.length; i++) {
        //必须拼接 不然eval解析{}或者字符串就会出现错误
        args.push(`arguments[${i}]`);
      }
    
      //oj对象调用fn函数 this指向改为ob
      //源码中使用eval函数处理多个参数 es6未出现之前的处理方式
      //存在问题
      const result = eval(`ob.fn(${args})`);
    
      // 执行完删除fn属性 防止原来obj结构被修改
      delete ob.fn;
    
      // 接收函数返回值
      return result;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    Es6实现call方法

    Function.prototype.call= function (ob, ...args) {
      // 如果不指定为this指向 默认window
      ob = ob || window;
    
      //把调用函数在oj里面新添加属性fn存一份
      ob.fn = this;
    
      //oj对象调用fn函数 this指向改为ob
      const result = ob.fn(...args);
    
      // 执行完删除fn属性 防止原来obj结构被修改
      delete ob.fn;
    
      // 接收函数返回值
      return result;
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    apply实现

    Function.prototype.apply= function (ob, args) {
      // 如果不指定为this指向 默认window
      ob = ob || window;
    
      //把调用函数在oj里面新添加属性fn存一份
      ob.fn = this;
    
      //oj对象调用fn函数 this指向改为ob
      let result = args ? ob.fn(...args) : ob.fn();
    
      // 执行完删除fn属性 防止原来obj结构被修改
      delete ob.fn;
    
      // 接收函数返回值
      return result;
    };
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    bind实现

    Function.prototype.bind= function (context, ...params) {
      // context->obj  params->[10,20]  this->fn
      let self = this;
      return function proxy(ev) {
        // this->submit ev->事件对象
        params = params.concat(ev);
        return self.call(context, ...params);
      };
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
  • 相关阅读:
    sql常用语法记录
    spring高级篇(三)
    一行代码禁止用户调试前端代码
    408真题-2021
    【电磁】基于 Biot-Savart 定律模拟沿螺旋(螺线管或环形)电流回路的磁场附matlab代码
    iptables与firewalld防火墙
    面向对象编程原则(08)——合成复用原则
    ROBOGUIDE软件:FANUC机器人弧焊焊接起始点接触寻位虚拟仿真
    站内搜索引擎
    机器学习第9天:决策树分类
  • 原文地址:https://blog.csdn.net/qq_44472790/article/details/126112172