zoukankan      html  css  js  c++  java
  • call,apply,bind的内部原理实现

    call

    call 方法使用一个函数执行的时候更改本身 this 指向,并传入一个或者多个参数。

    var obj = {
      name: '$call'
    }
    function _fun() {
      console.log(this.name, ...arguments)
    }
    
    _fun.call(obj, 'call1', 'call2', 'call3') // $call call1 call2 call3

    内部实现原理:

    Function.prototype.$$call = function (context) {
      // 第一个参数为 this 指向值,如无则指向 window
      context = context || window
      // 将本身的函数保存下来,在后面需要执行,这一步 this 的指向已经指向了 context 
      context.fn = this
      // 将后面传入的参数转为数组,取除第一个 this 指向剩下的所有参数
      let args = [...arguments].slice(1)
      // 执行函数本身,并将参数传入
      let result = context.fn(...args)
      // 销毁函数,避免作用域污染
      delete context.fn
      return result
    }

    apply

    apply 方法同 call 一样使用一个函数执行的时候更改本身 this 指向,只是传参的时候只有一个,并且必须是数组(如果call与apply传参类型记不清,可以根据方法的第一个字母来区分,apply -> a(首字母) -> array)。

    var obj = {
      name: '$call'
    }
    function _fun() {
      console.log(this.name, ...arguments)
    }
    
    _fun.apply(obj, ['call1', 'call2', 'call3']) // $call call1 call2 call3

    内部实现原理:

    Function.prototype.$$apply = function (context) {
      // 第一个参数为 this 指向值,如无则指向 window
      context = context || window
      // 将本身的函数保存下来,在后面需要执行,这一步 this 的指向已经指向了 context 
      context.fn = this
      // 将后面传入的参数转为数组,取除第二个参数
      let args = [...arguments][1]
      // 如果第二个参数不是对象则报错
      if (typeof args !== 'object') {
        throw Error('CreateListFromArrayLike called on non-object')
        return
      }
      // 执行函数本身,并将参数传入
      let result = context.fn(...args)
      // 销毁函数,避免作用域污染
      delete context.fn
      return result
    }

    bind

    bind 方法与 call 和 apply 不同的点是后续的参数没有要求,但是 bind 会返回一个 this 指向已改变的函数,相同的是第一个参数就是 this 指向值

    var obj = {
      name: '$call'
    }
    function _fun() {
      console.log(this.name, ...arguments)
    }
    
    _fun.call(obj, ['call1'], 'call3')('call2') // $call ["call1"] call3 call2

    内部实现原理:

    Function.prototype.$$bind = function (context) {
      // 取bind执行的时候除第一个后续的所有参数
      let args = [...arguments].slice(1)
      // 函数本身缓存
      let _this = this
      // 返回函数
      return function () {
        // 合并返回函数执行传入的参数
        let bindArg = [...args, ...arguments]
        // 再次调用时的函数本身执行
        return _this.call(context, ...bindArg)
      }
    }
  • 相关阅读:
    Qt BarChart实践
    Qt Charts_Audio实践
    Qt 报错LINK2019:无法解析的外部符号
    Qt Charts实践
    Qt Qwdget 汽车仪表知识点拆解8 淡入效果
    因果图法设计测试用例
    Jsoup获取部分页面数据失败 Unhandled content type. Must be text/*, application/xml, or application/xhtml+xml
    loadrunner入门篇
    如何对jmeter设置IP欺骗
    jmeter录制移动端脚本
  • 原文地址:https://www.cnblogs.com/kdcg/p/13225298.html
Copyright © 2011-2022 走看看