手寫實現(xiàn)call apply bind

call apply bind 區(qū)別

這三個都是Function中自帶的三個方法,都是可以改變this指向的,在Function.prototype上 可以打印看一下

console.dir(Function.prototype); //你會看的這三個屬性以及arguments,toString等屬性

call,apply的特點

  • 如果傳入的是值類型 this指向?qū)?yīng)類型的構(gòu)造函數(shù)創(chuàng)建的實例
  • 如果傳入的是對象 this指向?qū)ο蟊旧?/li>
  • 如果傳入 undefined 或者 null this為空對象

call apply bind 用法

 let name = "張三";
    let Person = {
      name: "法外狂徒",
      age: 18,
    };
    function say(lag) {
      console.log(this);
      console.log(`my name is ${this.name},my age is ${this.age},我說${lag}`);
    }
    say("I love you"); //此時會打印Window    my name is 張三,my age is undefined,我說I love you;此時this指的是window可以獲取到全局變量name
    //call
    say.call(Person , "I love you"); //my name is 法外狂徒,my age is 18,我說I love you, 此時函數(shù)中this就指向了Person
    //apply
    say.apply(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我說I love you  和call除了參數(shù)傳數(shù)組外沒什么不同
    //bind
    say.bind(Person, "I love you")(); //my name is 法外狂徒,my age is 18,我說I love you;bind返回的是一個函數(shù),需要執(zhí)行

實現(xiàn)call

在Function原型上加上自己的方法myCall;具體細節(jié)在注釋

Function.prototype.myCall = function (ctx, args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const key = Symbol(); //創(chuàng)建一個獨一無二的key以免覆蓋原有屬性
      ctx[key] = this; //將this賦值到傳入對象ctx的某一個屬性上;this指的是函數(shù),結(jié)合上下文這里this就是say函數(shù)
      const result = ctx[key](...args); //將入?yún)⒔鈽?gòu)傳入;并用result接收返回值
      delete ctx[key]; //用完后將此屬性刪除;不然每次call這個對象都會加個屬性
      return result; //返回函數(shù)返回值
    };
    //執(zhí)行myCall
    say.myCall(Person, ["I love you"]); //my name is 法外狂徒,my age is 18,我說I love you

實現(xiàn)apply

apply和call只是傳參區(qū)別,稍微修改下即可;直接復(fù)制過來

Function.prototype.myApply = function (ctx, ...args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const key = Symbol(); //創(chuàng)建一個獨一無二的key以免覆蓋原有屬性
      ctx[key] = this; //將this賦值到傳入對象ctx的某一個屬性上;this指的是函數(shù),結(jié)合上下文這里this就是say函數(shù)
      const result = ctx[key](...args); //將入?yún)⒔鈽?gòu)傳入;并用result接收返回值
      delete ctx[key]; //用完后將此屬性刪除;不然沒吃call這個對象都會加個屬性
      return result; //返回函數(shù)返回值
    };
 //執(zhí)行myApply
    say.myApply(Person, "I love you"); //my name is 法外狂徒,my age is 18,我說I love you

實現(xiàn)bind

bind 是返回一個函數(shù)

Function.prototype.myBind = function (ctx, ...args) {
      ctx = ctx ? Object(ctx) : window;
      args = args || [];
      const _this =this
      return function (...rest) {
        const key = Symbol(); //創(chuàng)建一個獨一無二的key以免覆蓋原有屬性
        console.log(this)//這里的this指向window,因為返回的是一個函數(shù),this永遠指向最后調(diào)用它的那個對象,最終調(diào)用這個函數(shù)的是window
        ctx[key] = _this; //將this賦值到傳入對象ctx的某一個屬性上;this指的是函數(shù),結(jié)合上下文這里this就是say函數(shù)
        const result = ctx[key](...args,...rest); //將入?yún)⒔鈽?gòu)傳入;并用result接收返回值
        delete ctx[key]; //用完后將此屬性刪除;不然沒吃call這個對象都會加個屬性
        return result; //返回函數(shù)返回值
      };
    };
    //執(zhí)行myBind
    say.myBind(Person, "I love you 1")(); //my name is 法外狂徒,my age is 18,我說I love you
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容