JavaScript手寫call,apply,bind方法
前言
改變this指向在書寫業(yè)務(wù)的時(shí)候經(jīng)常遇到,我們經(jīng)常采用以下方法進(jìn)行改寫
- 使用作用聲明變量存儲(chǔ)this
- 使用jJavaScript的原生方法call,apply,以及bind進(jìn)行改寫
第一種方法就不說了,就是一個(gè)變量存儲(chǔ)的問題,主要說第二種如何實(shí)現(xiàn)的
call,bind,apply方法都是JavaScript原生的方法,掛載在Function原型上,使得所有函數(shù)都可以調(diào)用,今天我們來實(shí)現(xiàn)一下call,apply,bind吧
改寫this實(shí)現(xiàn)思路
我們聲明一個(gè)函數(shù),函數(shù)接受倆個(gè)參數(shù),第一個(gè)參數(shù)是接受改變的this指向,第二個(gè)是剩余參數(shù),用于執(zhí)行改變方法后傳遞的使用參數(shù),在函數(shù)中里面聲明一個(gè)變量用于存儲(chǔ)傳遞過來的this,遵循this指向的準(zhǔn)則,this是在執(zhí)行的時(shí)候生成的,函數(shù)的準(zhǔn)則是誰調(diào)用它就指向誰,傳遞過來的this是一個(gè)對(duì)象,然后在傳遞過來的this上面聲明一個(gè)方法,聲明的方法就是當(dāng)前函數(shù),該方法由傳遞過來的this進(jìn)行調(diào)用執(zhí)行,這樣就改變了this指向問題,在把傳遞過來的參數(shù)除第一個(gè)外全部傳遞給聲明的方法,我們來實(shí)現(xiàn)一下
前期準(zhǔ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方法第一個(gè)參數(shù)都是改變的this指向,第二個(gè)參數(shù)是傳遞的參數(shù)
手寫call方法
call方法是改變this后立即執(zhí)行
Function.prototype.myCall = function(content, ...arg) { // 創(chuàng)建一個(gè)變量接受改變的this,如果改變的this為空則采用window為默認(rèn)this let newThis = content || window; /**newThis是一個(gè)對(duì)象,它是傳遞過來的this,在newThis上新增一個(gè)方法,這個(gè)方法就是 當(dāng)前函數(shù) ,this就是指向的myCall,調(diào)用這個(gè)方法就可以改變this指向,因?yàn)楹瘮?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ù),默認(rèn)為空數(shù)組 Function.prototype.myApply = function(content, arg = []) { // 判斷傳遞參數(shù)是否為數(shù)組,如果不為數(shù)組則拋出錯(cuò)誤,為數(shù)組則繼續(xù)執(zhí)行 if (!Array.isArray(arg)) { throw '傳遞參數(shù)必須為數(shù)組'; } // 創(chuàng)建一個(gè)變量接受改變的this,如果改變的this為空則采用window為默認(rèn)this let newThis = content || window; // 給當(dāng)前傳遞過來的this,添加一個(gè)方法,遵循this準(zhǔn)則,誰調(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í)行而是返回一個(gè)新的函數(shù)
Function.prototype.myBind = function(content, ...arg) { // 創(chuàng)建一個(gè)變量接受改變的this,如果改變的this為空則采用window為默認(rèn)this let newThis = content || window; // 給當(dāng)前傳遞過來的this,添加一個(gè)方法,遵循this準(zhǔn)則,誰調(diào)用就指向誰的原則 newThis.fn = this; // 由于bind不是立即執(zhí)行,是返回一個(gè)函數(shù)作為bind方法執(zhí)行的返回值,所以這里需要return出去一個(gè)函數(shù) return function() { // 然后在把執(zhí)行當(dāng)前的方法進(jìn)行執(zhí)行并把myBind接受剩余參數(shù)傳遞過去,接受返回值 let result = newThis.fn(...arg); //刪除當(dāng)前的函數(shù)以及傳遞過來的this,防止出現(xiàn)問題 delete newThis.fn; // 將執(zhí)行結(jié)果返回 return result; } }; //調(diào)用bind函數(shù),獲取返回值,他的返回值是一個(gè)函數(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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JS如何去掉小數(shù)末尾多余的0,并且最多保留兩位小數(shù)
這篇文章主要介紹了JS如何去掉小數(shù)末尾多余的0,并且最多保留兩位小數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04鼠標(biāo)事件的screenY,pageY,clientY,layerY,offsetY屬性詳解
這篇文章主要介紹了鼠標(biāo)事件的screenY,pageY,clientY,layerY,offsetY屬性詳解,需要的朋友可以參考下2015-03-03javascript驗(yàn)證身份證完全方法具體實(shí)現(xiàn)
下面這段代碼完全實(shí)現(xiàn)了判斷身份證是否合格.傳入身份證號(hào)碼就行了。包括了公安部的算法。下面的是用Ext實(shí)現(xiàn)的。但是基于javascript的語法居多,基本都可以用2013-11-11JS實(shí)現(xiàn)網(wǎng)頁搶購功能(觸發(fā),終止腳本)
小編通過一個(gè)網(wǎng)頁式的搶購功能的實(shí)現(xiàn)給大家講解一下JS如何觸發(fā)和終止腳本來完成這個(gè)任務(wù)。2017-11-11一文帶你掌握J(rèn)avaScript中的執(zhí)行上下文和作用域
作為一名前端工作人員,我們必須知道JavaScript內(nèi)部是如何執(zhí)行的。那對(duì)于執(zhí)行上下文和作用域的理解至關(guān)重要,無論是工作還是面試都是無法跳躍的一步,本文就來帶大家深入了解一下2023-02-02JS可視化學(xué)習(xí)向量計(jì)算點(diǎn)到線段的距離并展示
這篇文章主要為大家介紹了JS可視化學(xué)習(xí)向量計(jì)算點(diǎn)到線段的距離并展示實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12JavaScript實(shí)現(xiàn)找出字符串中第一個(gè)不重復(fù)的字符
這篇文章主要介紹了JavaScript實(shí)現(xiàn)找出字符串中第一個(gè)不重復(fù)的字符的方法,需要的朋友可以參考下2014-09-09JavaScript中使用正則匹配多條,且獲取每條中的分組數(shù)據(jù)
該問題在使用Ajax遠(yuǎn)程獲取某網(wǎng)頁數(shù)據(jù)時(shí)經(jīng)常遇見 如果目標(biāo)頁面是XML,就好辦了,實(shí)用XMLDOM可以很輕松完成任務(wù)。2010-11-11