关于前端:callapplybind的用法与区别以及使用场景

5次阅读

共计 3210 个字符,预计需要花费 9 分钟才能阅读完成。

前端工作和面试中常常会遇到批改 this 指向的问题, 这就避不开对 callapplybind 的探讨

用法

1. call

语法: function.call(thisArg, arg1, arg2, ...)
其中: thisArg 可选值; 指定为 nullundefined 时会主动替换为全局对象 (严格模式下将会是 undefined); 指定为数字、字符串或布尔类型, 则会转换成他们的包装对象. 是 function 函数运行时指向的 this 值. arg1, arg2, ... 指定的参数, 能够有多个
返回值: 调用有指定 this 值和参数的函数的后果。
应用场景:

    // 判断数据类型
    const a = 1
    const b = '1'
    const c = true
    const d = () => {}

    toString.call(a) // 输入 '[object Number]'
    toString.call(b) // 输入 '[object String]'
    toString.call(c) // 输入 '[object Boolean]'
    toString.call(d) // 输入 '[object Function]'

    // 将伪数组转换为数组
    function transformArgement() {const arr = Array.prototype.slice.call(arguments)
        return arr
    }

    console.log(transformArgement(1, 2, 3, 4, 5)) // 输入 [1, 2, 3, 4, 5]
    
    // 通过调用父构造函数的 call 办法来实现继承
    function Calc (args) {const arr = Array.prototype.slice.call(args)
        // 最大值
        this.max = Math.max.apply(null, arr)
        // 最小值
        this.min = Math.min.apply(null, arr)
        // 求和
        this.sum = arr.reduce((pre, cur) => pre + cur)
    }

    function Ages() {Calc.call(this, arguments)
        this.property = 'ages'
    }
    
    const team01 = new Ages(10, 20, 12, 80, 4, 100, 19)
    console.log(team01.min) // 输入 4
    console.log(team01.max) // 输入 100
    console.log(team01.sum) // 输入 245

2. apply

语法: function.apply(thisArg, argsArray)
其中: thisArg 用法同上. argsArray 指定的参数, 能够为一个数组或者类数组对象,其中的数组元素将作为独自的参数传给 function 函数
返回值: 调用有指定 this 值和参数的函数的后果。
应用场景:

    // 数组增加数组元素
    const arr1 = [1, 2, 3]
    const arr2 = ['1', '2', '3']

    Array.prototype.push.apply(arr1, arr2)
    console.log(arr1) // 输入 [1, 2, 3, '1', '2', '3']
    
    // 数组转化
    const slice = Array.prototype.slice;

    function args() {return slice.apply(arguments)
    }
    args(1, 2, 3, 4) // 返回 [1, 2, 3, 4]

    // 内置函数的扩大
    const arrNum = [1, 4, 6, 3, 2]
    console.log(Math.min.apply(null, arrNum))
    console.log(Math.max.apply(null, arrNum))

3. bind

语法: function.bind(thisArg, arg1, arg2, ...)
其中: thisArg 调用绑定函数时作为 this 参数传递给指标函数的值。如果应用 new 运算符结构绑定函数,则疏忽该值。当应用 bindsetTimeout 中创立一个函数(作为回调提供)时,作为 thisArg 传递的任何原始值都将转换为 object。如果 bind 函数的参数列表为空,或者 thisArgnullundefined,执行作用域的 this 将被视为新函数的 thisArg. arg1, arg2, ... 指定的参数, 能够有多个
返回值: 返回一个原函数的拷贝,并领有指定的 this 值和初始参数。
应用场景:

    // 创立绑定函数
    // 老手常常犯的一个谬误是将一个办法从对象中拿进去,而后再调用,冀望办法中的 this 是原来的对象
    this.a = 100
    const obj = {
        a: 1,
        fn: function() {return this.a}
    }
    
    obj.fn() // 输入 1

    const f = obj.fn.bind(obj)
    f() // 输入 1

    // React 组件中为函数绑定组件实例
    class Foo extends Component {constructor(props) {super(props);
            this.handleClick = this.handleClick.bind(this);
          }
          handleClick() {console.log('Click happened');
          }
          render() {return <button onClick={this.handleClick}>Click Me</button>;
        }
    }

    // 偏函数实现
    function add(arg1, arg2) {return arg1 + arg2}

    const addBase10 = add.bind(null, 10)
    console.log(addBase10(100)) // 输入 110
    console.log(addBase10(200)) // 输入 210
    
    // 类数组转化
    const unboundSlice = Array.prototype.slice
    const slice = Function.prototype.apply.bind(unboundSlice)
    
    function args() {return slice(arguments)
    }
    args(1, 2, 3, 4) // 返回 [1, 2, 3, 4]

区别

从下面的用法比照不难看出, callapply 次要是入参不同, 他们都是返回调用有指定 this 值和参数的函数的后果(即立刻调用)。而 bind 的入参加 call 雷同, 然而他的返回值与 callapply 都不同, 是一个原函数的拷贝,并领有指定的 this 值和初始参数。

延长

应用 js 实现 bind 办法

  • 首先须要把办法增加到函数原型
  • 办法能够承受 n 个参数, 其中第一个参数为调用办法的函数的 this 指向, 其余参数将作为调用函数的入参

      Function.prototype.customBind = function (targetThis) {
          // 类型校验
          if (toString.call(this) !=== '[object Function]') {throw new Error(`${this} mast be a Function`)
          }
          // 保留 this
          const _this = this
          // 保留参数(剔除第一个参数 - 须要 this 指向的参数)
          const args = Array.prototype.slice.call(arguments, 1)
          const fn = function () {
              // 保留调用时传入的参数
              const fnArgs = Array.prototype.slice.call(arguments)
              return _this.apply(targetThis, args.concat(fnArgs))
          }
          return fn
      }
      
      function fn() {console.log(this) // 输入 {a: 10}
        console.log(this.a, arguments) // Arguments [1, 2, 3, 4, 5, 6]
      }
      const o = {a: 10}
      fn.customBind(o, 1, 2, 3)(4, 5, 6)
正文完
 0