JavaScript-实现函数方法-改变this指向call apply bind

this

  • 函数执行时决定的不是定义时决定的
  • this只和函数的调用有关*
  • obj.fn() fnthis就是obj arr[0] () this就是arr

重定义

call

  • 会直接执行函数
  • 函数的参数逐个传进去
实现
  • 首先先判断thisArg参数 如果为空就默认window 这里运用了||运算符 有一个t结果就为t 所以短路效果为前面的表达式结果为t 后面的表达式就不执行

补充说明&&运算符 前面一个f结果就为f 所以短路效果是前面为f后面不执行

  • symbol(基本数据类型)有唯一性 可以保证属性与原对象不冲突 let key = Symbol('temp')创建一个symbol类型的变量key其中temp是这个变量的描述符
  • 利用对象的方法中的this指向对象 :通过把这个函数给thisArg对象的方法再通过这个对象调用就改变了函数this的指向 其中利用数组的展开运算符 把value(剩余参数数组)挨个传进这个方法完成了mycall改变this指向和直接执行函数的功能
js 复制代码
    //实现call
    Function.prototype.myCall = function (thisArg, ...value) {
      //如果参数为空 就默认是window
      //利用||特性
      thisArg = thisArg || window

      let key = Symbol('temp')
      thisArg[key] = this
      //利用...数组的展开运算符把value的所有元素 逐个全部传入
      thisArg[key](...value)
      delete thisArg[key]

    }
  • 测试用例
js 复制代码
//测试用例
    //this指向对象
    function fnCall(a, b) {
      console.log(this, a, b);
    }
    fnCall.myCall(obj, 1, 2)
    //this指向函数
    function fn1() {
      console.log('这是测试函数');
    }
    fnCall.myCall(fn1, 1, 2)

apply

  • 也会直接执行函数
  • 参数以对象(一般是数组的形式传进去)
实现

mycall的基本思想是一样的区别如下

  • 因为参数是数组形式 所以myApply中的value参数不需要用剩余参数数组...value直接获取传入的数组value即可 然后还是使用...展开运算符把参数数组展开传入
js 复制代码
 //实现apply
     Function.prototype.myApply = function (thisArg, value) {
      thisArg = thisArg || window
      let key = Symbol('temp')
      thisArg[key] = this
      //利用...数组的展开运算符把value的所有元素 逐个全部传入
      thisArg[key](...value)
      delete thisArg[key]
    }
    fnCall.myApply(obj, [1, 2])
  • 测试用例同mycall

bind

  • 参数逐个传入
  • 返回新数组 调用之后才执行(参数自动传进去 this改变)
实现

不会立即执行函数 而是返回新的函数

  • 因为返回的新函数中的this就不是调用函数了 所以要把this放进fn函数里
  • 返回一个新函数 先给thisArg对象添加fn方法(就是要改变this的函数) 然后把原函数的返回结果 也就是对象方法的结果原函数的返回结果放进result作为新函数的返回结果 删除属性避免对原thisArg造成干扰 最后把result变量return出去

举例子(没有this干扰)理解result变量的必要性 这里把内部函数的返回值return出去 就能实现调用outside函数返回一个inside函数并且把他的她的返回值也复制了最终代码

js 复制代码
 //实现bind
    //创建新函数 this绑定到指定对象上
    Function.prototype.myBind = function (thisArg, ...value) {
      //不会立即执行函数 而是返回新的函数
      thisArg = thisArg || window
      let fn = this //把调用的函数存起来
      return function () {
        let key = Symbol('temp') //每次调用都创建新的临时键
        thisArg[key] = fn
        const result = thisArg[key](...value)
        delete thisArg.fn
        return result  //返回原函数的执行结果
      }
    }
  • 测试用例
js 复制代码
//生成新的函数
    function bindFn(a, b) {
      console.log('myBind结果', this, a, b);
    }
    let Person = {
      name: 'a'
    }
    const newBindfn = bindFn.myBind(Person, 2, 1)
//传入thisArg为空的情况
    const newBindfn1 = bindFn.myBind('', 2, 3)  //this指向window
//新生成的函数返回值
    function fn() {
      return '函数返回结果'
    }
    console.log(fn.myBind(Person)());//函数返回结果
相关推荐
地狱恶犬萨煤耶1 小时前
JavaScript-小游戏-单词消消乐
javascript
tyro曹仓舒2 小时前
干了10年前端,才学会使用IntersectionObserver
前端·javascript
mine_mine3 小时前
油猴脚本拦截fetch和xhr请求,实现修改服务端接口功能
javascript
一 乐3 小时前
考公|考务考试|基于SprinBoot+vue的考公在线考试系统(源码+数据库+文档)
前端·javascript·数据库·vue.js·spring boot·课程设计
林太白4 小时前
跟着TRAE SOLO全链路看看项目部署服务器全流程吧
前端·javascript·后端
特级业务专家4 小时前
把 16MB 中文字体压到 400KB:我写了一个 Vite 字体子集插件
javascript·vue.js·vite
先生沉默先4 小时前
NodeJs 学习日志(8):雪花算法生成唯一 ID
javascript·学习·node.js
起这个名字4 小时前
Webpack——插件实现的理解
前端·javascript·node.js
二川bro5 小时前
第51节:Three.js源码解析 - 核心架构设计
开发语言·javascript·ecmascript