• js call apply bind


    call、apply、bind
    cat.call(dog, a, b) == cat.apply(dog, [a, b]) == (cat.bind(dog, a, b))()

    1.作用
    改变函数内的this指向
    var name = 'window',
    foo = {name: 'foo'};
    function fn () {
    console.log(this.name)
    }
    fn();//window
    fn.call(foo);//foo

    2.用法
    call 语法: foo.call(this, arg1,arg2, ... ,argn );
    apply 语法: foo.apply(this, [ arg1,arg2, ... ,argn ] );
    bind 语法: foo.bind(this);

    3.区别
    1)参数
    call: 可以有n个参数,从第二个参数开始的所有参数都是原函数的参数。
    apply:只有两个参数,并且第二个参数必须为数组,数组中的所有元素一一对应原函数的参数。
    bind: 只有一个参数,即要绑定的this。

    2)调用
    call apply:调用后立即执行
    bind:调用后返回已经绑定this的函数

    4.应用
    1)伪数组转为数组
    [].slice.call(arr);
    2)取数组最大最小值
    var arr = [1,2,3,4];
    Math.max.apply(Math, arr) == Math.max(...arr);//4
    3)合并数组
    var arr1 = [1,2], arr2 = [3,4];
    [].push.apply(arr1, arr2) == arr1.concat(arr2) == [...arr1, ...arr2];

    5.手写

    1)call

    Function.prototype.myCall = function(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      context = context || window
      context.fn = this
      const args = [...arguments].slice(1)
      const result = context.fn(...args)
      delete context.fn
      return result
    }
    • 首先 context 为可选参数,如果不传的话默认上下文为 window
    • 接下来给 context 创建一个 fn 属性,并将值设置为需要调用的函数
    • 因为 call 可以传入多个参数作为调用函数的参数,所以需要将参数剥离出来
    • 然后调用函数并将对象上的函数删除

    2)apply

    Function.prototype.myApply = function(context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      context = context || window
      context.fn = this
      let result
      // 处理参数和 call 有区别
      if (arguments[1]) {
        result = context.fn(...arguments[1])
      } else {
        result = context.fn()
      }
      delete context.fn
      return result
    }

    3)bind

    Function.prototype.myBind = function (context) {
      if (typeof this !== 'function') {
        throw new TypeError('Error')
      }
      const _this = this
      const args = [...arguments].slice(1)
      // 返回一个函数
      return function F() {
        // 因为返回了一个函数,我们可以 new F(),所以需要判断
        if (this instanceof F) {
          return new _this(...args, ...arguments)
        }
        return _this.apply(context, args.concat(...arguments))
      }
    }
    • 前几步和之前的实现差不多,就不赘述了
    • bind 返回了一个函数,对于函数来说有两种方式调用,一种是直接调用,一种是通过 new 的方式,我们先来说直接调用的方式
    • 对于直接调用来说,这里选择了 apply 的方式实现,但是对于参数需要注意以下情况:因为 bind 可以实现类似这样的代码 f.bind(obj, 1)(2),所以我们需要将两边的参数拼接起来,于是就有了这样的实现 args.concat(...arguments)
    • 最后来说通过 new 的方式,在之前的章节中我们学习过如何判断 this,对于 new 的情况来说,不会被任何方式改变 this,所以对于这种情况我们需要忽略传入的 this

    参考:1.https://segmentfault.com/a/1190000011389726
       2.https://segmentfault.com/a/1190000014182270

  • 相关阅读:
    NC20565 生日礼物(双指针)
    NC20566 游戏(二分图)
    NC19833 地斗主(dp+矩阵快速幂)
    CF505C Mr. Kitayuta, the Treasure Hunter(dp)
    HDU5493 Queue(线段树)
    HDU5489 Removed Interval (LIS+分治)
    CF1158C Permutation recovery(线段树优化建图)
    NC20811 蓝魔法师(树形dp)
    NC20857 Xor Path(dfs)
    chrony同步时间
  • 原文地址:https://www.cnblogs.com/bear-blogs/p/9864891.html
Copyright © 2020-2023  润新知