总结一下call、apply、bind的用法和心得

首先三者的作用:

首先问个问题,这三个函数的存在意义是什么?答案是改变函数执行时的上下文,再具体一点就是改变函数运行时的this指向

代码演示

      function Star(name) {
        this.name = name;
      }
      Star.prototype = {
        constructor: Star,
        like: function (...args) {
          console.log(`${this.name}喜欢唱歌,传递参数:${args}`);
        },
      };
      var star = new Star("刘德华");
      star.like(123);
      //刘德华喜欢唱歌,传递参数:123

后台打印的是:刘德华喜欢唱歌,传递参数:123

接下来

      const person={
        name:'张三'
      }

上面代码中有一个对象字面量,他没有所谓like的方法,但是我还是想用?怎么办?此时,call、apply、bind可以帮我们干这件事。

      star.like.call(person,1)
      star.like.apply(person,[2])
      star.like.bind(person,[3])()
    //   张三喜欢唱歌,传递参数:1
    //   张三喜欢唱歌,传递参数:2
    //   张三喜欢唱歌,传递参数:3

可以调用了,这就是它们的作用。

总结一下,就是我们动态改变了对象的上下文,也就是改变了this的指向,复用了另一个对象的方法(属性也可以)。在此可以打印this来看一下,眼见为实。

      Star.prototype = {
        constructor: Star,
        like: function (...args) {
            console.log(this);
          console.log(`${this.name}喜欢唱歌,传递参数:${args}`);
        },
      };

 可以看到指向的是name为张三的对象

区别

那都是改变this的指向,一个不就好了吗,为何要三个呢,直接上代码,体验区别。

        let person1 = {
          name: "张三",
          age: 12,
          say(...args) {
            console.log(`姓名:${this.name},年龄:${this.age},参数:${args}`);
          },
        };

        let person2 = {
          name: "李四",
          age: 14,
        };
        //call第一个参数: 借用方法的对象,可以传递多个参数
        person1.say.call(person2, 123, 2, 5, 3);
        //姓名:李四,年龄:14,参数:123,2,5,3

        //call第一个参数: 借用方法的对象,允许传递第二个参数必须是数组
        person1.say.apply(person2, [2, 3, 4, 5]);
        //姓名:李四,年龄:14,参数:2,3,4,5

        // bind只是改变了this的指向,但是并没有调用say方法,加一个()执行
        person1.say.bind(person2, [1, 2])();
        // 姓名:李四,年龄:14,参数:1,2
        person1.say.bind(person2, 2, 3, 4)();
        // 姓名:李四,年龄:14,参数:2,3,4

简而言之:

call和aplly的第一个参数都是要改变上下文的对象,而call从第二个参数开始以参数列表的形式展现,apply则是把除了改变上下文对象的参数放在一个数组里面作为它的第二个参数。

call和apply改变了函数的this上下文后便执行该函数,而bind则是返回改变了上下文后的一个函数,并且既可以一个一个参数传入,也可以用数组

应用

  1. 求数组中的最大和最小值
  2. 将伪数组转化为数组
  3. 数组追加
  4. 判断变量类型
  5. 实现继承
  • 求数组中的最大和最小值
  • const arr = [1,2,3,-3,456,-299,78,22];
            Math.max.call(Math,1,2,3,-3,456,-299,78,22)
            Math.max.apply(Math,arr)
            //456
            //当然es6更简单点 Math.max(...arr)
    
  • 将伪数组转化为数组
  • js中的伪数组(例如通过document.getElementsByTagName获取的元素)具有length属性,并且可以通过0、1、2…下标来访问其中的元素,但是没有Array中的push、pop等方法。我们可以利用call、apply来将其转化为真正的数组这样便可以方便地使用数组方法了

    如querySelectAll, getElementsByClassNmae, arguments等
    args =Array.prototype.slice.call(arg,0); //slice方法传入0返回原数组

  • 数组追加

  • var arr1 = [1, 2, 3];
          var arr2 = [4, 5, 6];
          Array.push.apply(arr1, arr2);
          // arr1 [1, 2, 3, 4, 5, 6]
          // arr2 [4,5,6]
          //es6 [...arr1,...arr2]

  • 判断变量类型

  •       const a=1
          const b='1'
          const c={}
          const d=[]
          const e=function(){}
          console.log(Object.prototype.toString.call(a));
          console.log(Object.prototype.toString.call(b));
          console.log(Object.prototype.toString.call(c));
          console.log(Object.prototype.toString.call(d));
          console.log(Object.prototype.toString.call(e));
          //  [object Number]
          //  [object String]
          //  [object Object]
          //  [object Array]
          //  [object Function]
  • 实现继承

  •       var Person = function (name, age) {
            this.name = name;
            this.age = age;
          };
          var Girl = function (name) {
            Person.call(this, name);
          };
          var Boy = function (name, age) {
            Person.apply(this, arguments);
          };
          var g1 = new Girl("ldh");
          var b1 = new Boy("lbb", 100);

    结尾:网上的教程有很多,最重要的是自己将代码敲一遍。光看不练假把式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值