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