JavaScript手寫call,apply,bind方法
前言
改變this指向在書寫業(yè)務(wù)的時候經(jīng)常遇到,我們經(jīng)常采用以下方法進行改寫
- 使用作用聲明變量存儲this
- 使用jJavaScript的原生方法call,apply,以及bind進行改寫
第一種方法就不說了,就是一個變量存儲的問題,主要說第二種如何實現(xiàn)的
call,bind,apply方法都是JavaScript原生的方法,掛載在Function原型上,使得所有函數(shù)都可以調(diào)用,今天我們來實現(xiàn)一下call,apply,bind吧
改寫this實現(xiàn)思路
我們聲明一個函數(shù),函數(shù)接受倆個參數(shù),第一個參數(shù)是接受改變的this指向,第二個是剩余參數(shù),用于執(zhí)行改變方法后傳遞的使用參數(shù),在函數(shù)中里面聲明一個變量用于存儲傳遞過來的this,遵循this指向的準則,this是在執(zhí)行的時候生成的,函數(shù)的準則是誰調(diào)用它就指向誰,傳遞過來的this是一個對象,然后在傳遞過來的this上面聲明一個方法,聲明的方法就是當前函數(shù),該方法由傳遞過來的this進行調(diào)用執(zhí)行,這樣就改變了this指向問題,在把傳遞過來的參數(shù)除第一個外全部傳遞給聲明的方法,我們來實現(xiàn)一下
前期準備
這些數(shù)據(jù)用于配合手寫的方法,由于call,bind,apply他們都是需要把他們掛載到函數(shù)原型上,函數(shù)才能調(diào)用的到,我們這里也把他掛載到原型上
var name = '前端'; var age = "7"; let obj = { name: '若水', age: '20' }; function fnLog(arg) { let str = `我叫${this.name}今年${this.age}歲了`; console.log(str, '傳遞過來的', arg); }
手寫的call,bind,apply方法第一個參數(shù)都是改變的this指向,第二個參數(shù)是傳遞的參數(shù)
手寫call方法
call方法是改變this后立即執(zhí)行
Function.prototype.myCall = function(content, ...arg) { // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; /**newThis是一個對象,它是傳遞過來的this,在newThis上新增一個方法,這個方法就是 當前函數(shù) ,this就是指向的myCall,調(diào)用這個方法就可以改變this指向,因為函數(shù)是誰調(diào)用 它this就指向誰 **/ newThis.fn = this; /**執(zhí)行改變this方法,接受返回值,這里容易被誤導(dǎo),這里是把myCall傳遞過來的參數(shù)傳遞 給了改變this的函數(shù),由于不確定傳遞多少使用了剩余參數(shù),這里也是 **/ let result = newThis.fn(...arg); //刪除傳遞過來this上聲明的方法,防止出現(xiàn)問題 delete newThis.fn; // 將執(zhí)行結(jié)果返回 return result; }; //執(zhí)行手寫的call方法 fnLog.myCall(obj, 'myCall');
手寫apply方法
apply傳遞的參數(shù)只能傳遞數(shù)組
//如果arg沒有傳遞參數(shù),默認為空數(shù)組 Function.prototype.myApply = function(content, arg = []) { // 判斷傳遞參數(shù)是否為數(shù)組,如果不為數(shù)組則拋出錯誤,為數(shù)組則繼續(xù)執(zhí)行 if (!Array.isArray(arg)) { throw '傳遞參數(shù)必須為數(shù)組'; } // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; // 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調(diào)用就指向誰的原則 newThis.fn = this; // 同mycall相同 let result = newThis.fn(arg); //刪除傳遞過來this上聲明的方法,防止出現(xiàn)問題 delete newThis.fn; // 將執(zhí)行結(jié)果返回 return result; }; //執(zhí)行 fnLog.myApply(obj, [1, 212, 232]);
手寫bind方法
bind不是立即執(zhí)行而是返回一個新的函數(shù)
Function.prototype.myBind = function(content, ...arg) { // 創(chuàng)建一個變量接受改變的this,如果改變的this為空則采用window為默認this let newThis = content || window; // 給當前傳遞過來的this,添加一個方法,遵循this準則,誰調(diào)用就指向誰的原則 newThis.fn = this; // 由于bind不是立即執(zhí)行,是返回一個函數(shù)作為bind方法執(zhí)行的返回值,所以這里需要return出去一個函數(shù) return function() { // 然后在把執(zhí)行當前的方法進行執(zhí)行并把myBind接受剩余參數(shù)傳遞過去,接受返回值 let result = newThis.fn(...arg); //刪除當前的函數(shù)以及傳遞過來的this,防止出現(xiàn)問題 delete newThis.fn; // 將執(zhí)行結(jié)果返回 return result; } }; //調(diào)用bind函數(shù),獲取返回值,他的返回值是一個函數(shù),所以我們需要在調(diào)用一下 let f1 = fnLog.myBind(obj, 2); //調(diào)用bind的返回值 f1()
到此這篇關(guān)于JavaScript手寫call,apply,bind方法的文章就介紹到這了,更多相關(guān)JavaScript call內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS如何去掉小數(shù)末尾多余的0,并且最多保留兩位小數(shù)
這篇文章主要介紹了JS如何去掉小數(shù)末尾多余的0,并且最多保留兩位小數(shù)問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2023-04-04鼠標事件的screenY,pageY,clientY,layerY,offsetY屬性詳解
這篇文章主要介紹了鼠標事件的screenY,pageY,clientY,layerY,offsetY屬性詳解,需要的朋友可以參考下2015-03-03JS實現(xiàn)網(wǎng)頁搶購功能(觸發(fā),終止腳本)
小編通過一個網(wǎng)頁式的搶購功能的實現(xiàn)給大家講解一下JS如何觸發(fā)和終止腳本來完成這個任務(wù)。2017-11-11一文帶你掌握JavaScript中的執(zhí)行上下文和作用域
作為一名前端工作人員,我們必須知道JavaScript內(nèi)部是如何執(zhí)行的。那對于執(zhí)行上下文和作用域的理解至關(guān)重要,無論是工作還是面試都是無法跳躍的一步,本文就來帶大家深入了解一下2023-02-02JavaScript實現(xiàn)找出字符串中第一個不重復(fù)的字符
這篇文章主要介紹了JavaScript實現(xiàn)找出字符串中第一個不重復(fù)的字符的方法,需要的朋友可以參考下2014-09-09JavaScript中使用正則匹配多條,且獲取每條中的分組數(shù)據(jù)
該問題在使用Ajax遠程獲取某網(wǎng)頁數(shù)據(jù)時經(jīng)常遇見 如果目標頁面是XML,就好辦了,實用XMLDOM可以很輕松完成任務(wù)。2010-11-11