Apply的理解

Apply 和 Call一樣在 函數調用的時候會改變函數內的this指向,讓this變成 Apply或Call的第一個參數。

舉個例子:

 var ObjEngineer = {
    name:'程序員努力的一天',
    age:19
 };

 function fn2() {
     console.log(this.name);
 }

fn2.Apply(ObjEngineer )

輸出:
   程序員努力的一天

是不是感覺 this.name 的值被 ObjEnginner中的 name給覆蓋了呢,就是的。

解刨一下原理:

自定一個 myCall吧,把 myCall 掛載到 Function上,這樣每個函數都可以使用myCall

Function.prototype.myCall = function(context){ 
    context.fn = this; //這裏的this是指誰調用 myCall 就指向誰,比如: b.myCall ,這個 this 就指向 b
    context.fn();
    delete context.fn;
 }

上面代碼是先給context對象添加一個 fn的函數,把外面調用 myCall的函數傳給 context.fn, 當 context.fn() 執行完之後就可以把他刪除掉了不用了。 

如果帶有參數的方式呢? 

升級一下

 Function.prototype.myCall = function(context,arr){
    let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函數明和 自定的函數明(fn)重名
    context[fn] = this; //this 指向調用者,比如下面的fn2
    context[fn](...arr); //傳遞參數
    delete context[fn];
 }

 var ObjEngineer = {
    name:'程序員努力的一天',
    age:19
 };

 function fn2(age,email) {
     console.log(this.name+" 年齡:"+age+" Email: "+email);
 }

 fn2.myCall(ObjEngineer,[19,'[email protected]']) //第二個參數接收數組方式

輸出:

程序員努力的一天 年齡:19 Email: [email protected]

 

如果調用的函數有返回值咋辦?

 在升級一下

 Function.prototype.myCall = function(context,arr){
    let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函數明和 自定的函數明(fn)重名
    context[fn] = this;
    let res = context[fn](...arr); //傳遞參數
    delete context[fn];
    return res;
 }

 var ObjEngineer = {
    name:'程序員努力的一天',
    age:19
 };

 //帶有返回值的
 function fn2(age,email) {
     console.log(this.name+" 年齡:"+age+" Email: "+email);
     return {age,email} 
 }

 let res = fn2.myCall(ObjEngineer,[19,'[email protected]']) //第二個參數接收數組方式
 console.log(res);
 

輸出:

程序員努力的一天 年齡:19 Email: 189@qq.com
{age: 19, email: '[email protected]'}

上面的myCall還不夠完善,當沒有 obj 和 arr 參數的時候就有問題,在完善一下。

 

 Function.prototype.myCall = function(context,arr){
    context = context || window //沒有contenxt的時候,就指向window
    let fn = Symbol() //ES6中的Symbol唯一性,就是防止 this中的函數明和 自定的函數明(fn)重名
    context[fn] = this;
    let res =  !arr ? context[fn]() : context[fn](...arr); //傳遞參數,沒有參數的時候也要處理一下
    delete context[fn];
    return res;
 }

 

 

參考:https://www.bilibili.com/video/BV1s3411g7gU/?spm_id_from=333.337.search-card.all.click&vd_source=02f2aad32c21e62474c9d52666b96f92

https://www.cnblogs.com/GoodPingGe/p/16145199.html

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章