call,bind,apply绑定this

函数的call方法, 可以指定this

函数的call方法, 可以在触发函数的同时替换其this指向

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 函数call方法
      // 函数默认情况下: 函数中this指向其所在的对象!
      // 利用call可以强制修改 函数中this的指向!
​
      var name = "全局区域";
​
      var yanan = {
        name: "亚楠",
        intro: function () {
          console.log(`${this.name} 是最棒的!`);
          console.log("this:", this);
        },
      };
​
      yanan.intro(); // 亚楠
      // 函数是对象类型 -- 函数诞生 new Function()
      // 对象类型是引用类型
      var intro = yanan.intro;
      intro(); // 全局区域
​
      // 利用call强制替换函数 执行时 的 this
      console.log("利用call 替换函数的this 然后执行");
      intro.call(yanan);
​
      intro.call({ name: "亮亮" });
      // 伪代码: call实现了什么
      // 相当于: intro.this = {name:"亮亮"}
      //         intro()
​
      function demo() {
        console.log("demo.this:", this);
      }
      // 执行时, 把demo中的this 替换成 参数1: yanan
      demo.call(yanan);
    </script>
  </body>
</html>

call方法仿写

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // call的使用场景:
      // 函数.call(对象):  函数执行时就相当于是放在 参数对象 中执行
      // 其中的this会指向 指定的对象
      Function.prototype._call = function (obj) {
        // 此处的this 就相当于是
        // var demo = new Function("console.log(this.name)");
        // fn是自定义的属性
        obj.fn = this; //this是当前函数, 保存到了对象里
        // 对象调用函数: 函数中的this指向其所在的对象!
        obj.fn(); //函数的this 就变为了obj, 即传入的对象
      };
      // var demo = new Function('console.log(this.name)')
      function demo() {
        console.log(this.name);
      }
​
      var obj;
      obj = { name: "亮亮" };
      demo._call(obj);
​
      demo._call({ name: "铭铭" });
    </script>
  </body>
</html>
​
<script>
  Function.prototype._call = function (obj) {
    // demo._call(obj):  所以_call函数中的this 就是demo
    obj.fn = this;
    obj.fn();
  };
​
  function demo() {
    console.log(this.name);
  }
​
  var obj;
  obj = { name: "亮亮" };
  demo._call(obj);
​
  function show() {
    // 函数中的this指向函数执行时所在的对象
    console.log(this.name);
  }
​
  var obj1 = { name: "亚楠" };
  // 对象.属性名 = 值;  属性名不存在就会自动创建
  obj1.fn = show;
  console.log(obj1);
  obj1.fn();
​
  var obj1 = {
    name: "亚楠",
    // fn: function show() {
    //   console.log(this.name);
    // },
  };
  obj1.fn = function show() {
    console.log(this.name);
  };
  obj1.fn();
</script>

call使用场景

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 用途: 当创建多个类似的构造函数时, 会有很多共同的属性, 可以提取这些共同的属性 组成一个 共享的构造函数
​
      // 函数.call(新对象):  就会把函数的this替换成新对象, 然后触发函数
      // 构造函数: 创建员工对象
      function Employee(name, age, eid) {
        this.name = name;
        this.age = age;
        this.eid = eid;
      }
      // 员工中细分为: 教师 管理者 ...
      function Teacher(name, age, eid) {
        // show(a,b,c); //调用时有三个参数
        // 如果用call来修改this指向, 则写法为:
        // show.call(新的对象, a,b,c)
        // call(新的this, ...其他参数)
​
        // 调用时 把Employee的this 换成当前的
        // new Teacher() 得到的对象  -- 即 亚楠
        // 所以内容生成的属性 都属于 当前的Teacher 对象
        Employee.call(this, name, age, eid);
        // this.name = name;
        // this.age = age;
        // this.eid = eid;
​
        this.category = "教师"; //分类 = 教师
      }
      var yanan = new Teacher("亚楠", 19, "110011");
      console.log(yanan);
​
      // 员工=>管理者
      function Manager(name, age, eid) {
        // 利用员工函数 Employee 生成管理者的 其他通用属性
​
        // 函数的形式: 对象.函数();  函数的this就是其前面的对象
        // 下方写法, 相当于是 window.Employee
        // Employee(name, age, eid); //会导致函数内的this指向window
        Employee.call(this, name, age, eid);
​
        this.category = "管理者";
      }
      var m = new Manager("文华", 38, "100001");
      console.log(m);
    </script>
  </body>
</html>

apply

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // 函数的apply: 同call, 都可以替换函数的this指向, 同时执行函数
      // 同一个函数:  show(a,b,c);  对象obj
      // 用call书写: show.call(obj, a,b,c)
      // 用apply书写: show.apply(obj, [a,b,c])
      // 特点:  apply(对象, [参数数组..])
      let obj = { name: "楠楠" };
​
      function show(a, b, c) {
        console.log(this.name, a, b, c);
      }
​
      show.call(obj, 1, 2, 3);
      show.apply(obj, [1, 2, 3]);
    </script>
  </body>
</html>

apply用途

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // apply的用途:
      // Math的max()方法: 用来求出参数中的最大值
      console.log(Math.max(12, 32, 435, 435, 34546));
​
      // 求数组中的最大值
      var nums = [123, 435, 34, 13, 435, 453, 213];
      // max: 此方法只能判断 参数是数字的情况, 无法直接传递数组
      console.log(Math.max(nums)); //NaN: not a numebr- 不是数字
​
      // apply: 可以把数组类型 转化成 普通的函数参数结构
      // 没有this指向的问题, 参数1不用传
      var a = Math.max.apply(null, nums);
      console.log(a);
​
      // 合并数组:
      var arr1 = [1, 2, 3, 4];
      var arr2 = [11, 22, 33, 44];
      // 回顾: 可以用concat合并
      // var arr = arr1.concat(arr2);
      // console.log(arr);
      arr1.push(99, 88, 77, 66);
      // apply: 参数arr1 必须要写, 代表执行 apply的对象
      arr1.push.apply(arr1, arr2);
      // ES6提供的语法糖, ... 可以拆解数组变为参数
      arr1.push(...arr2);
      console.log(arr1);
    </script>
  </body>
</html>

函数的bind方法

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // bind: 为函数绑定this, 返回绑定了this的新函数, 但是不立即执行
      // 注意: bind不会修改原函数, 而是克隆一个新的出来, 把this替换了
      var yanan = { name: "亚楠" };
​
      var name = "全局";
​
      function show() {
        console.log(this.name);
      }
      //show1 是bind返回的新函数, 利用window方式查看, 可以发现这个函数带有一个 boundThis 属性, 其中就保存了 yanan 对象
      // 正常函数: 本身不保存this指向, 会根据其运行所在的对象作为他的this
      // 通过bind创建的函数, 带有 boundThis属性, 则调用时 就用把这个属性作为自己的this
      var show1 = show.bind(yanan);
​
      show1();
      show();
    </script>
  </body>
</html>

bind的用途

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <script>
      // bind的用途:
      function Demo(count) {
        this.count = count;
      }
​
      Demo.prototype._countdown = function () {
        // 本质是 window.setInterval(): 所以此函数是在window对象中执行的
        setInterval(function () {
          // 此处的this就是window, 相当于是 widnow.count--
          // 由于window中没有 count 变量, 所以出现 NaN
          // 自增++  自减--   a-- 相当于 a = a-1
          console.log(this.count--);
        }, 1000);
      };
      // d.countdown()
      Demo.prototype.countdown = function () {
        // 不要用默认的箭头函数, 此函数就是为了解决普通函数的bug而生的
        // 利用bind方式, 把当前对象绑定给回调函数
        var callback = function () {
          console.log("this:", this);
          console.log(this.count--);
        };
        // cb 变量, 存储了 绑定了 this 变量的 函数
        var cb = callback.bind(this);
        window.cb = cb;
​
        setInterval(cb, 1000);
​
        // setInterval(() => {
        //   console.log(this.count--);
        // }, 1000);
      };
​
      var d = new Demo(1000);
      d.countdown();
​
      // 定时器: sti
      // 参数1: 回调函数
      // 参数2: 时间间隔, 单位ms 毫秒.  1秒=1000毫秒
      // setInterval: 属于window的
      // 所以函数中的this 就是window
      // setInterval(function () {
      //   console.log("this:", this);
      //   console.log(new Date().toTimeString());
      // }, 1000);
    </script>
  </body>
</html>
​
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

abssss1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值