美文网首页
Web前端------JS高级apply、call、bind方法

Web前端------JS高级apply、call、bind方法

作者: Peak_One | 来源:发表于2018-07-07 18:18 被阅读39次
    JS apply、call、bind方法使用介绍

    在介绍apply 、call、bind方法之前很有必要做一下简单的铺垫,因为apply、call、bind方法牵涉到改变function内部this(即函数所属【或调用对象】的问题),所以将函数内部this的指向问题进行介绍:

    • 函数内部this的指向
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
      <title>Document</title>
    </head>
    <body>
    
    </body>
    </html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        /*
         *
         * 函数中的this的指向
         *
         *
         * 普通函数中的this是谁?-----window
         * 对象.方法中的this是谁?----当前的实例对象
         * 定时器方法中的this是谁?----window
         * 构造函数中的this是谁?-----实例对象
         * 原型对象方法中的this是谁?---实例对象
         *
         *
         * */
    
        //严格模式:
    //    "use strict";//严格模式
    //    function f1() {
    //      console.log(this);//window
    //    }
    //    f1();
    
    
        //普通函数
        //    function f1() {
        //      console.log(this);
        //    }
        //   f1();
    
        //定时器中的this
        //    setInterval(function () {
        //      console.log(this);
        //    },1000);
    
        //构造函数
        //    function Person() {
        //      console.log(this);
        //对象的方法
        //      this.sayHi=function () {
        //        console.log(this);
        //      };
        //    }
        //原型中的方法
        //    Person.prototype.eat=function () {
        //      console.log(this);
        //    };
        //    var per=new Person();
        //    console.log(per);
        //    per.sayHi();
        //    per.eat();
        //BOM:中顶级对象是window,浏览器中所有的东西都是window的
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    
    • 函数声明与函数表达式的区别
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        //函数声明
    //
    //    if(true){
    //      function f1() {
    //        console.log("哈哈,我又变帅了");
    //      }
    //    }else{
    //      function f1() {
    //        console.log("小苏好猥琐");
    //      }
    //    }
    //    f1();
    
    
        //函数表达式
    
        var ff;
        if(true){
          ff=function () {
            console.log("哈哈,我又变帅了");
          };
        }else{
          ff=function () {
            console.log("小苏好猥琐");
          };
        }
        ff();
    
        //函数声明如果放在if-else的语句中,在IE8的浏览器中会出现问题
        //以后宁愿用函数表达式,都不用函数声明
      </script>
    </head>
    <body>
    </body>
    </html>
    
    • 拓展:数组的函数调用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        //数组可以存储任何类型的数据
    
        var arr=[
            function () {
              console.log("十一假期快乐");
            },
            function () {
              console.log("十一假期开心");
            }
            ,
            function () {
              console.log("十一假期健康");
            }
            ,
            function () {
              console.log("十一假期安全");
            },
            function () {
              console.log("十一假期如意");
            }
        ];
        //回调函数:函数作为参数使用
        arr.forEach(function (ele) {
          ele();
        });
    
    
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    
    apply和call方法的使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        //apply和call的使用
        //作用:可以改变this的指向
    
    //    function f1(x,y) {
    //      console.log("结果是:"+(x+y)+this);
    //      return "10000";
    //    }
    //    f1(10,20);//函数的调用
    
    
        //console.log("========");
        //此时的f1实际上是当成对象来使用的,对象可以调用方法
        //apply和call方法也是函数的调用的方式
        //f1.apply();
        //f1.call();
        //console.log("==========");
        //f1.apply(null);
        //f1.call(null);
    
        //apply和call方法中如果没有传入参数,或者是传入的是null,那么调用该方法的函数对象中的this就是默认的window
    
        //f1.apply(null,[100,200]);
        //f1.call(null,100,200);
    
        //apply和call都可以让函数或者方法来调用,传入参数和函数自己调用的写法不一样,但是效果是一样的
    
    //    var result1=f1.apply(null,[10,20]);
    //    var result2=f1.call(null,10,20);
    //    console.log(result1);
    //    console.log(result2);
    
    
    
    
    
    //    function f1(x,y) {
    //      console.log("这个函数是window对象的一个方法:"+(x+y)+this.sex);
    //    }
    //    window.f1(10,20);
    //    //obj是一个对象
    //    var obj={
    //      age:10,
    //      sex:"男"
    //    };
    //
    //    window.f1.apply(obj,[10,20]);
    //    window.f1.call(obj,10,20);
    //    console.dir(obj);
    
    
        //apply和call可以改变this的指向
    
    
        function Person(age,sex) {
          this.age=age;
          this.sex=sex;
        }
        //通过原型添加方法
        Person.prototype.sayHi=function (x,y) {
          console.log("您好啊:"+this.sex);
          return 1000;
        };
        var per=new Person(10,"男");
        per.sayHi();
    
        console.log("==============");
        function Student(name,sex) {
          this.name=name;
          this.sex=sex;
        }
        var stu=new Student("小明","人妖");
        var r1=per.sayHi.apply(stu,[10,20]);
        var r2=per.sayHi.call(stu,10,20);
    
        console.log(r1);
        console.log(r2);
    
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    

    总结:apply和call方法总结

    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        //apply和call都可以改变this的指向
        //函数的调用,改变this的指向
        //    function f1(x,y) {
        //      console.log((x+y)+":===>"+this);
        //      return "这是函数的返回值";
        //    }
        //    //apply和call调用
        //    var r1=f1.apply(null,[1,2]);//此时f1中的this是window
        //    console.log(r1);
        //    var r2=f1.call(null,1,2);//此时f1中的this是window
        //    console.log(r2);
        //    console.log("=============>");
        //    //改变this的指向
        //    var obj={
        //      sex:"男"
        //    };
        //    //本来f1函数是window对象的,但是传入obj之后,f1函数此时就是obj对象的
        //    var r3=f1.apply(obj,[1,2]);//此时f1中的this是obj
        //    console.log(r3);
        //    var r4=f1.call(obj,1,2);//此时f1中的this是obj
        //    console.log(r4);
    
    
        //方法改变this的指向
    
    //    function Person(age) {
    //      this.age = age;
    //    }
    //    Person.prototype.sayHi = function (x, y) {
    //      console.log((x + y) + ":====>" + this.age);//是实例对象
    //    };
    //
    //    function Student(age) {
    //      this.age = age;
    //    }
    //    var per = new Person(10);//实例对象
    //    var stu = new Student(100);//实例对象
    //    //sayHi方法是per实例对象的
    //    per.sayHi.apply(stu, [10, 20]);
    //    per.sayHi.call(stu, 10, 20);
    
    
        //apply和call的使用方法
        /*
        * apply的使用语法
        * 函数名字.apply(对象,[参数1,参数2,...]);
        * 方法名字.apply(对象,[参数1,参数2,...]);
        * call的使用语法
        * 函数名字.call(对象,参数1,参数2,...);
        * 方法名字.call(对象,参数1,参数2,...);
        *
        * 作用:改变this的指向
        * 不同的地方:参数传递的方式是不一样的
        *
        * 只要是想使用别的对象的方法,并且希望这个方法是当前对象的,那么就可以使用apply或者是call的方法改变this的指向
        *
        * */
    
    
        function f1() {
          console.log(this+":====>调用了");
        }
        //f1是函数,f1也是对象
        console.dir(f1);
        //对象调用方法,说明,该对象中有这个方法
        f1.apply();
        f1.call();
        console.log(f1.__proto__==Function.prototype);
        //所有的函数都是Function的实例对象
        console.log(Function.prototype);//ƒ () { [native code] }
        console.dir(Function);
        //apply和call方法实际上并不在函数这个实例对象中,而是在Function的prototype中
    
    
        function Person() {
          this.sayHi=function () {
            console.log("您好");
          };
        }
        Person.prototype.eat=function () {
          console.log("吃");
        };
    
        var per=new Person();
        per.sayHi();
        per.eat();
        console.dir(per);
        //实例对象调用方法,方法要么在实例对象中存在,要么在原型对象中存在
    
     </script>
    </head>
    <body>
    
    
    </body>
    </html>
    
    bind方法的使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        function f1(x, y) {
          console.log((x + y) + ":=====>" + this.age);
        }
    
    
        //复制了一份的时候,把参数传入到了f1函数中,x===>10,y===>20,null就是this,默认就是window
        //bind方法是复制的意思,参数可以在复制的时候传进去,也可以在复制之后调用的时候传入进去
        //apply和call是调用的时候改变this指向
        //bind方法,是赋值一份的时候,改变了this的指向
    
    
        //    var ff=f1.bind(null);
        //    ff(10,20);
    
    
    //    function Person() {
    //      this.age = 1000;
    //    }
    //    Person.prototype.eat = function () {
    //      console.log("这个是吃");
    //    };
    //    var per = new Person();
    //
    //    var ff = f1.bind(per, 10, 20);
    //    ff();
    
    
    
    
        function Person(age) {
          this.age=age;
        }
        Person.prototype.play=function () {
          console.log(this+"====>"+this.age);
        };
    
        function Student(age) {
          this.age=age;
        }
        var per=new Person(10);
        var stu=new Student(20);
        //复制了一份
        var ff=per.play.bind(stu);
        ff();
        //bind是用来复制一份
        //使用的语法:
        /*
        * 函数名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个函数
        * 方法名字.bind(对象,参数1,参数2,...);---->返回值是复制之后的这个方法
        *
        * */
    
    
    
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    
    bind方法的应用小demo
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
        //通过对象,调用方法,产生随机数
    
        function ShowRandom() {
          //1-10的随机数
          this.number=parseInt(Math.random()*10+1);
        }
        //添加原型方法
        ShowRandom.prototype.show1=function () {
          //改变了定时器中的this的指向了,本来应该是window,现在是实例对象了
          window.setInterval(this.show2.bind(this),1000);
        };
        //添加原型方法
        ShowRandom.prototype.show2=function () {
          //显示随机数--
          console.log(this.number);
        };
        //实例对象
        var sr=new ShowRandom();
        //调用方法,输出随机数字
        //调用这个方法一次,可以不停的产生随机数字
        sr.show1();
      </script>
    </head>
    <body>
    
    </body>
    </html>
    
    函数作为参数使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
    
    //    function f1(fn) {
    //      console.log("f1的函数");
    //      fn();//此时fn当成是一个函数来使用的
    //    }
    //    //fn是参数,最后作为函数使用了,函数是可以作为参数使用
    //    //传入匿名函数
    //    f1(function () {
    //      console.log("我是匿名函数");
    //    });
    //    //命名函数
    //    function f2() {
    //      console.log("f2的函数");
    //    }
    //    f1(f2);
    //    //函数作为参数的时候,如果是命名函数,那么只传入命名函数的名字,没有括号
    
    
    
    //    function f1(fn) {
    //      setInterval(function () {
    //        console.log("定时器开始");
    //        fn();
    //        console.log("定时器结束");
    //      },1000);
    //    }
    //
    //    f1(function () {
    //      console.log("好困啊,好累啊,就是想睡觉");
    //    });
    
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    
    函数作为返回值使用
    <!DOCTYPE html>
    <html lang="en">
    <head>
      <meta charset="UTF-8">
      <title>title</title>
      <script>
    
    
        //    function f1() {
        //      console.log("f1函数开始");
        //      return function () {
        //        console.log("我是函数,但是此时是作为返回值使用的");
        //      }
        //
        //    }
        //
        //    var ff=f1();
        //    ff();
    
    
        //    var num=10;
        //    console.log(typeof num);//获取num这个变量的数据类型
        //    var obj={};//对象
        //    //判断这个对象是不是某个类型的
        //    console.log(obj instanceof Object);
        //    //获取某个对象的数据类型的样子
        //    //Object.prototype.toString.call(对象);//此时得到的就是这个对象的类型的样子
        //
        //
        //
        //    //此时输出的是Object的数据类型   [object Object]
        //    console.log(Object.prototype.toString());
        //    //输出的数组的数据类型      [object Array]
        //    console.log(Object.prototype.toString.call([]));
        //
        //    var arr=[10,20,30];
        //    console.log(Object.prototype.toString.call(arr));
        //
        console.log(Object.prototype.toString.call(new Date()));
    
    
        //获取某个对象的类型是不是你传入的类型
        //[10,20,30] 是不是"[object Array]"
        //type---是变量----是参数----"[object Array]"
        //obj---是变量-----是参数----[10,20,30];
    
        //判断这个对象和传入的类型是不是同一个类型
        function getFunc(type) {
          return function (obj) {
            return Object.prototype.toString.call(obj) === type;
          }
        }
    
        var ff = getFunc("[object Array]");
        var result = ff([10, 20, 30]);
        console.log(result);
    
        var ff1 = getFunc("[object Object]");
        var dt = new Date();
        var result1 = ff1(dt);
        console.log(result1);
    
    
      </script>
    </head>
    <body>
    
    
    </body>
    </html>
    

    欢迎关注我的个人微信公众号,免费送计算机各种最新视频资源!你想象不到的精彩!


    0.jpg

    相关文章

      网友评论

          本文标题:Web前端------JS高级apply、call、bind方法

          本文链接:https://www.haomeiwen.com/subject/mujguftx.html