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

2018-07-07  本文已影响39人  Peak_One
JS apply、call、bind方法使用介绍

在介绍apply 、call、bind方法之前很有必要做一下简单的铺垫,因为apply、call、bind方法牵涉到改变function内部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
上一篇下一篇

猜你喜欢

热点阅读