版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
第一文搞懂JavaScript中bind,apply,call的實(shí)現(xiàn)目錄bind、call和apply的用法bindcallapply實(shí)現(xiàn)bind實(shí)現(xiàn)call和apply總結(jié)bind、call和apply都是Function原型鏈上面的方法,因此不管是使用function聲明的函數(shù),還是箭頭函數(shù)都可以直接調(diào)用。這三個(gè)函數(shù)在使用時(shí)都可以改變this指向,本文就帶你看看如何實(shí)現(xiàn)bind、call和apply。
bind、call和apply的用法
bind
bind()方法可以被函數(shù)對(duì)象調(diào)用,并返回一個(gè)新創(chuàng)建的函數(shù)。
語(yǔ)法:
function.bind(thisArg[,arg1[,arg2[,...]]])
bind()會(huì)將第一個(gè)參數(shù)作為新函數(shù)的this,如果未傳入?yún)?shù)列表,或者第一個(gè)參數(shù)是null或undefined,那么新函數(shù)的this將會(huì)是該函數(shù)執(zhí)行作用域的this。使用bind()應(yīng)注意以下事項(xiàng):
返回一個(gè)新的函數(shù),但是不會(huì)立即執(zhí)行該函數(shù)根據(jù)傳入的參數(shù)列表綁定this指向,如果未傳入thisArg,那么需要明確this的指向如果是箭頭函數(shù),無(wú)法改變this,只能改變參數(shù),這一點(diǎn)我們?cè)谶@些情況下不建議你使用箭頭函數(shù)也講到過(guò)
舉個(gè)例子:
正常使用
functionfn(a){
console.log(this,a)
constfn1=fn.bind({x:100});//fn1是一個(gè)函數(shù),但是并沒(méi)有立即執(zhí)行
fn1();//{x:100}100
console.log(fn===fn1);//false,bind返回的是一個(gè)新的函數(shù)
箭頭函數(shù)
constfn=(a)={
console.log(this,a);
constfn1=fn.bind({x:100},100);//返回一個(gè)新的函數(shù)fn1,不會(huì)執(zhí)行
fn1();//window,100箭頭函數(shù)通過(guò)bind返回的函數(shù)無(wú)法修改其this指向
未綁定this,或綁定到null、undefined
constfn=(a)={
console.log(this,a);
constfn1=fn.bind();//未綁定
constfn2=fn.bind(null);//綁定null
constfn3=fn.bind(undefined);//綁定undefined
fn1();//綁定到執(zhí)行作用域,默認(rèn)為window
fn2();//綁定到執(zhí)行作用域,默認(rèn)為window
fn3();//綁定到執(zhí)行作用域,默認(rèn)為window
callapply
與bind不同,call和apply都是用來(lái)執(zhí)行函數(shù)的,可以解決執(zhí)行的函數(shù)的this指向問(wèn)題。
語(yǔ)法:
function.call(thisArg,arg1,arg2,...)
function.apply(thisArg,argsArray)
call的參數(shù)列表是可選的,如果傳入的thisArg是null或者undefined,那么會(huì)自動(dòng)替換為全局對(duì)象;如果是傳入的原始值,則會(huì)替換為原始值對(duì)應(yīng)的包裝類型。apply的用法和call類似,不同點(diǎn)在于其額外傳入的參數(shù)是一個(gè)數(shù)組或類數(shù)組對(duì)象,而call的額外參數(shù)是不確定參數(shù)。
舉個(gè)栗子:
functionfn(a,b){
console.log(this,a,b);
fn.call({x:100},10,20);//{x:100}1020
fn.apply({x:100},[10,20]);//{x:100}1020
call和apply無(wú)法修改箭頭函數(shù)的this指向:
constfn=(a,b)={
console.log(this,a,b);
fn.call({x:100},10,20);//Window1020
fn.apply({x:100},[10,20]);//Window1020
簡(jiǎn)單回顧了以下bind、call、apply的使用,接下來(lái)就看看應(yīng)該如何來(lái)實(shí)現(xiàn)。
實(shí)現(xiàn)bind
根據(jù)我們剛剛使用的bind(),在設(shè)計(jì)時(shí)需要如下考慮:
最終返回的是一個(gè)新的函數(shù),可通過(guò)function來(lái)聲明需要綁定新函數(shù)的this需要綁定運(yùn)行時(shí)的參數(shù),可通過(guò)apply或call來(lái)實(shí)現(xiàn)
實(shí)現(xiàn)代碼:
//通過(guò)原型鏈注冊(cè)方法
//context:傳遞的上下文this;bindArgs表示需要綁定的額外參數(shù)
Ftotype.newBind=function(context,...bindArgs){
constself=this;//當(dāng)前調(diào)用bind的函數(shù)對(duì)象
//返回的函數(shù)本身也是可以再傳入?yún)?shù)的
returnfunction(...args){
//拼接參數(shù)
constnewArgs=bindArgs.concat(args);
returnself.apply(context,newArgs)
functionfn(a,b){
console.log(this,a,b);
constfn1=fn.newBind({x:100},10);
fn1(20);//{x:100}1020
bind()返回的是一個(gè)新函數(shù),執(zhí)行新函數(shù)就相當(dāng)于是通過(guò)call或apply來(lái)調(diào)用原函數(shù),并傳入this和參數(shù)。
實(shí)現(xiàn)call和apply
在實(shí)現(xiàn)bind的過(guò)程中,我們使用了apply來(lái)完成this的綁定,那么要實(shí)現(xiàn)apply又應(yīng)該用什么來(lái)綁定this呢?可能會(huì)有小機(jī)靈鬼發(fā)現(xiàn),好像在apply中使用call,在call中使用apply也可以完成this綁定。這不就形成了嵌套嘛,不是我們最終想要的。
我們先來(lái)
call和apply的應(yīng)用:
bind返回一個(gè)新的函數(shù),并不會(huì)執(zhí)行;call和apply會(huì)立即執(zhí)行函數(shù)綁定this傳入執(zhí)行參數(shù)
舉個(gè)栗子:
functionfn(a,b){
console.log(this,a,b);
fn.call({x:100},10,20);//{x:100}1020
fn.apply({x:100},[10,20]);//{x:100}1020
call和apply的實(shí)現(xiàn)效果是一樣的,都是立即執(zhí)行函數(shù),不同的是call需要傳入單個(gè)或者多個(gè)參數(shù),apply可以傳入一個(gè)參數(shù)數(shù)組。
如何在函數(shù)執(zhí)行時(shí)綁定this:
constobj={x:100,fn(){this.x}}執(zhí)行obj.fn(),此時(shí)fn()內(nèi)部的this指向的就是obj可以借此實(shí)現(xiàn)函數(shù)綁定this
使用過(guò)Vue的朋友都知道,Vue實(shí)例其實(shí)就是一個(gè)對(duì)象,其里面的方法在調(diào)用時(shí),this就會(huì)指向當(dāng)前對(duì)象。舉個(gè)栗子:
letobj={
key:'key',
getKey:()={
returnthis.key;
getKey2(){
returnthis.key;
obj.getKey();//this指向window,返回值取決于window中是否有對(duì)應(yīng)的屬性
obj.getKey2();//this指向obj,返回'key'
這個(gè)例子在這些情況下不建議你使用箭頭函數(shù)也是有提及的,感興趣的朋友可以去看看。根據(jù)此原理,我們就可以來(lái)嘗試給函數(shù)綁定this了:某函數(shù)調(diào)用apply,那么我們就將這個(gè)函數(shù)添加到傳入的this對(duì)象中(如果未傳入則this為全局對(duì)象,如果傳入的是原始值,則使用其包裝類型),然后使用()來(lái)執(zhí)行函數(shù),這個(gè)時(shí)候函數(shù)的this指向的就是我們傳入的this了。
實(shí)現(xiàn)代碼:
Ftotype.newCall=function(context,...args){
if(context==null)context=globalThis;//如果傳入的上下文是null或者undefined,則使用全局globalThis,一般指向的就是window
if(typeofcontext!=='object')context=newObject(context);//如果是原始類型(數(shù)字、字符串、布爾值等),則使用其包裝類型
constfnKey=Symbol();//使用Symbol可確保key值不會(huì)重復(fù),避免屬性覆蓋
context[fnKey]=this;//this指向的是當(dāng)前調(diào)用newCall的函數(shù)
console.log(context[fnKey]);//打印當(dāng)前函數(shù)以及上下文this
console.log(context);
constres=context[fnKey](...args);//執(zhí)行函數(shù),函數(shù)的this指向?yàn)閏ontext
deletecontext[fnKey];//刪除fn,防止污染
returnres;//返回結(jié)果
fn.newCall({x:100},10,20);//{x:100}1020
functionfn(a,b){
console.log(this,a,b);
這樣我們就實(shí)現(xiàn)了call,那么apply實(shí)現(xiàn)類似,只不過(guò)傳入的額外參數(shù)要變成數(shù)組或類數(shù)組的方式
Ftotype.newCall=function(context,args){
if(context==null)context=globalThis;//如果傳入的上下文是null或者undefined,則使用全局globalThis,一般指向的就是window
if(typeofcontext!=='object')context=newObject(context);//如果是原始類型(數(shù)字、字符串、布爾值等),則使用其包裝類型
constfnKey=Symbol();//使用Symbol可確保key值不會(huì)重復(fù),避免屬性覆蓋
context[fnKey]=this;//this指向的是當(dāng)前調(diào)用newCall的函數(shù)
console.log(context[fnKey]);//打印當(dāng)前函數(shù)以及上下文this
console.log(context);
constres=context[fnKey](...args);//執(zhí)行函數(shù),函數(shù)的this指向?yàn)閏ontext
deletecontext[fnKey];//刪除fn,防止污染
returnres;//返回結(jié)果
fn.newCall({x:100},10,20);//{x:100}1020
functionfn(a,b){
console.log(this,a,b);
注意打印的當(dāng)前函數(shù)以及上下文:
實(shí)現(xiàn)call和apply與bind有很大的不同就是如何來(lái)處理this
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 2026江蘇省常州市體育運(yùn)動(dòng)學(xué)校招聘排球教練1人備考題庫(kù)及一套完整答案詳解
- 江蘇省東臺(tái)市三倉(cāng)中學(xué)2026屆高一上數(shù)學(xué)期末質(zhì)量跟蹤監(jiān)視模擬試題含解析
- 罕見腫瘤的個(gè)體化治療治療策略優(yōu)化經(jīng)驗(yàn)與案例
- 罕見腫瘤的個(gè)體化治療療效預(yù)測(cè)模型構(gòu)建與個(gè)體化路徑
- 2025貴州興義市人民醫(yī)院引進(jìn)高層次、急需緊缺人才100人備考題庫(kù)及一套答案詳解
- 電商會(huì)計(jì)財(cái)務(wù)制度
- 生產(chǎn)經(jīng)營(yíng)類企業(yè)財(cái)務(wù)制度
- 石油公司財(cái)務(wù)制度
- 2026江蘇南京大學(xué)招聘?jìng)淇碱}庫(kù)XZ2025-428醫(yī)學(xué)院專業(yè)、技術(shù)人員備考題庫(kù)有完整答案詳解
- 學(xué)校社團(tuán)章程財(cái)務(wù)制度
- 途虎養(yǎng)車安全培訓(xùn)課件
- 衛(wèi)生管理研究論文
- 2025-2026學(xué)年人教版(新教材)小學(xué)數(shù)學(xué)二年級(jí)下冊(cè)(全冊(cè))教學(xué)設(shè)計(jì)(附教材目錄P161)
- 委托市場(chǎng)調(diào)研合同范本
- 畜牧安全培訓(xùn)資料課件
- 2025年度黨支部書記述職報(bào)告
- 2026四川省引大濟(jì)岷水資源開發(fā)限公司公開招聘易考易錯(cuò)模擬試題(共500題)試卷后附參考答案
- 2026年安徽糧食工程職業(yè)學(xué)院高職單招職業(yè)適應(yīng)性考試備考試題及答案詳解
- 內(nèi)科學(xué)總論小兒遺傳代謝病課件
- 雨課堂學(xué)堂在線學(xué)堂云《中國(guó)電影經(jīng)典影片鑒賞(北京師范大學(xué))》單元測(cè)試考核答案
- 核電站防地震應(yīng)急方案
評(píng)論
0/150
提交評(píng)論