call apply bind使用原理及JS手写

文章目录

前言

call apply bind,这三者都是用来改变函数的this对象的指向的。
通俗来讲就是,东风之礼,借来可用

一、使用上的异同

1. 相似之处:

都是用来改变函数的this对象的指向的。
第一个参数都是this要指向的对象。
都可以利用后续参数传参。

2. 不同之处

call 的传参是单个传参
apply 传参是以一个数组的行书
bind 非常特殊,可在对象后追加,也可以在传参数进行输入

二、call详细用法

1. 通俗解释

字面意思是“借用”,“请求”,一个场景:当你十分想抽烟,结果手里没带火机,也没有烟,这时候你需要去借烟和活(虽然是有点过分)

2. 代码案例
  var smokeMe = {
        name: "没有香烟",
        tool: "没有火机",
        smoking: function (a, b) {
          alert("我在用" + this.tool + "点" + this.name + "==>" + a + b);
        },
      };
      var smokerYou = {
        name: "宇宙牌香烟",
        tool: "石英火机",
      };
      smokeMe.smoking.call(smokerYou, "白嫖", "心里美滋滋");
3. Js手写call

首先context为可选参数,如果不传的话默认上下文是window
接下来给content创建一个fn属性,并将值设置为需要调用的函数
因为call可以传入多个参数作为调用函数的参数,所有需要将参数剥离出来
然后调用函数并将对象上的函数删除

Function.prototype.Mycall = function (val) {
        val = val || window;
        val.fn = this;
        const args = [...arguments].slice(1);
        const result = val.fn(...args);
        delete val.fn;
        return result;
      };
smokeMe.smoking.Mycall(smokerYou, "白嫖", "心里美滋滋");

apply详细用法

1. 代码案例

使用方法与call一致,传入第二个参数的形式是数组

smokeMe.smoking.apply(smokerYou,["白嫖", "心里美滋滋"]);
2. Js手写apply
 Function.prototype.myApply = function (context) {
        if (typeof this !== "function") {
          throw new TypeError("Error");
        }
        context = context || window;
        context.fn = this;
        let result;
        if (arguments[1]) {
          result = context.fn(...arguments[1]);
        } else {
          result = context.fn();
        }
        delete context.fn;
        return result;
      };
      smokeMe.smoking.apply(smokerYou,["白嫖", "心里美滋滋"]);

bind详细用法

1. 代码案例

使用方法与call传参形式也可以,在后面传参也可以

   smokeMe.smoking.bind(smokerYou,"白嫖", "心里美滋滋")();
    smokeMe.smoking.bind(smokerYou)("白嫖", "心里美滋滋");
    smokeMe.smoking.bind(smokerYou,["白嫖", "心里美滋滋"])();
    smokeMe.smoking.bind(smokerYou)(["白嫖", "心里美滋滋"]);
2. Js手写bind
   Function.prototype.myApply = function (context) {
        if (typeof this !== "function") {
          throw new TypeError("Error");
        }
        context = context || window;
        context.fn = this;
        let result;
        if (arguments[1]) {
          result = context.fn(...arguments[1]);
        } else {
          result = context.fn();
        }
        delete context.fn;
        return result;
      };
   smokeMe.smoking.bind(smokerYou)("白嫖", "心里美滋滋");

综合Demo

<!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>
    <style>
      .box {
        width: 800px;
        height: 500px;
        border: 1px solid #ccc;
        margin: 20px auto;
      }

      .box-title {
        text-align: center;
      }

      .showList {
        height: 290px;
        width: 90%;
        margin: 10px auto;
        border: 1px solid #ccc;
        overflow: auto;
      }
      .counts {
        position: relative;
      }
      .demo {
        white-space: pre;
      }
      .main {
        position: absolute;
        right: 0%;
        width: 520px;
        height: 24px;
        top: 10%;
        border: 1px #ccc solid;
        background-color: #cccccc;
      }
      .title {
        position: absolute;
        right: 3px;
        top: 4px;
        width: 520px;
        height: 24px;
      }
    </style>
  </head>

  <body>
    <div class="box">
      <h1 class="box-title">call apply bind</h1>
      <div style="margin-left: 45%">
        <button onclick="setfun()">函数调用</button>
        <button onclick="setCall()">call</button>
        <button onclick="setApply()">apply</button>
        <button onclick="setBind()">bind</button>
      </div>
      <div>
        <div class="showList">
          <div class="counts">
            <div class="demo"></div>
            <div class="main"></div>
            <div class="title">显示结果区域:(<span class="idea"></span>)</div>
          </div>
        </div>
      </div>
    </div>
  </body>
  <script>
    let showUl = document.querySelector(".counts");
    let showMain = document.querySelector(".main");
    let showDemo = document.querySelector(".demo");
    let showIdea = document.querySelector(".idea");
    var showText = "";
    var obj1 = {
      name: "猿人甲",
      gender: "男",
      age: 24,
      watchThis: function (a, b) {
        showText =
          this.name +
          " , " +
          this.gender +
          " ,今年" +
          this.age +
          ",参数:" +
          a +
          b;
      },
    };
    var obj2 = {
      name: "媛人乙",
      gender: "女",
      age: 18,
    };
    showDemo.innerHTML = `
    var obj1 = {
      name: "猿人甲",
      gender: "男",
      age: 24,
      watchThis: function (a, b) {
        showText = this.name + " , " + this.gender + " ,今年" + this.age +"参数" +
          a +
          b; ;
      },
    };
    var obj2 = {
      name: "媛人乙",
      gender: "女",
      age: 18,
    };`;
    function setfun() {
      obj1.watchThis();
      showMain.innerHTML = "obj1.watchThis()====>" + showText;
      showIdea.innerHTML = "直接调用函数,this指向的是上一级实例对象";
    }
    function setCall() {
      obj1.watchThis.call(obj2, "单", "个");
      showMain.innerHTML = "obj1.watchThis.call(obj2)====>" + showText;
      showIdea.innerHTML = "call()方法将obj.watchThis方法this指向obj2";
    }
    function setApply() {
      obj1.watchThis.apply(obj2, ["数", "组"]);
      showMain.innerHTML = "obj1.watchThis.apply(obj2)====>" + showText;
      showIdea.innerHTML = "apply()方法将obj.watchThis方法this指向obj2";
    }
    function setBind() {
      // obj1.watchThis.bind(obj2)("单", "个");
      obj1.watchThis.bind(obj2, "单", "个")();
      showMain.innerHTML = "obj1.watchThis.bind(obj2)()====>" + showText;
      showIdea.innerHTML = "bind()以方法将obj.watchThis方法this指向obj2";
    }
  </script>
</html>
上一篇:(数据科学学习手札126)Python中JSON结构数据的高效增删改操作


下一篇:centos7 安装gitlab