亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                bind、call、apply 區(qū)別?如何實(shí)現(xiàn)一個(gè)bind?

                為什么要改變this指向?

                我們知道bind,call,apply的作用都是用來(lái)改變this指向的,那為什么要改變this指向呢?請(qǐng)看下面的例子:

                var name=”lucy”;let obj={ name:”martin”, say:function () { console.log(this.name); }};obj.say(); //martin,this指向obj對(duì)象setTimeout(obj.say,0); //lucy,this指向window對(duì)象

                可以觀察到,正常情況下 say 方法中的 this 是指向調(diào)用它的 obj 對(duì)象的,而定時(shí)器 setTimeout 中的 say 方法中的 this 是指向window對(duì)象的(在瀏覽器中),這是因?yàn)?say 方法在定時(shí)器中是作為回調(diào)函數(shù)來(lái)執(zhí)行的,因此回到主棧執(zhí)行時(shí)是在全局執(zhí)行上下文的環(huán)境中執(zhí)行的,但我們需要的是 say 方法中 this 指向obj對(duì)象,因此我們需要修改 this 的指向。

                作用

                call、apply、bind作用是改變函數(shù)執(zhí)行時(shí)的上下文,簡(jiǎn)而言之就是改變函數(shù)運(yùn)行時(shí)的this指向

                那么什么情況下需要改變this的指向呢?下面舉個(gè)例子

                var name = “lucy”;var obj = { name: “martin”, say: function () { console.log(this.name); }};obj.say(); // martin,this 指向 obj 對(duì)象setTimeout(obj.say,0); // lucy,this 指向 window 對(duì)象

                從上面可以看到,正常情況say方法輸出martin

                但是我們把say放在setTimeout方法中,在定時(shí)器中是作為回調(diào)函數(shù)來(lái)執(zhí)行的,因此回到主棧執(zhí)行時(shí)是在全局執(zhí)行上下文的環(huán)境中執(zhí)行的,這時(shí)候this指向window,所以輸出lucy

                我們實(shí)際需要的是this指向obj對(duì)象,這時(shí)候就需要該改變this指向了

                setTimeout(obj.say.bind(obj),0); //martin,this指向obj對(duì)象

                區(qū)別

                下面再來(lái)看看apply、call、bind的使用

                apply

                apply接受兩個(gè)參數(shù),第一個(gè)參數(shù)是this的指向,第二個(gè)參數(shù)是函數(shù)接受的參數(shù),以數(shù)組的形式傳入,且當(dāng)?shù)谝粋€(gè)參數(shù)為null、undefined的時(shí)候,默認(rèn)指向window(在瀏覽器中),使用apply方法改變this指向后原函數(shù)會(huì)立即執(zhí)行,且此方法只是臨時(shí)改變thi指向一次。

                先上一個(gè)例子,比較好理解

                var foo = {value: 1};function bar(name, age) {console.log(name)console.log(age)console.log(this.value);}bar.apply(foo, [‘kevin’, 18]);// kevin// 18// 1

                值得注意的事情是,當(dāng)使用apply()方法時(shí),控制臺(tái)會(huì)打印出我們所希望打印的內(nèi)容,也就是bar函數(shù)執(zhí)行了,在改變其this指向后,執(zhí)行改變后的函數(shù),關(guān)于這一點(diǎn),call()方法的執(zhí)行也是一樣的。

                顯然我們傳入的數(shù)組,會(huì)被正確解析為bar中所需要的參數(shù)

                日常用法:改變this指向

                function fn(…args){ console.log(this,args);}let obj = { myname:”張三”}fn.apply(obj,[1,2]); // this會(huì)變成傳入的obj,傳入的參數(shù)必須是一個(gè)數(shù)組;fn(1,2) // this指向window

                當(dāng)?shù)谝粋€(gè)參數(shù)為null、undefined的時(shí)候,默認(rèn)指向window(在瀏覽器中)

                fn.apply(null,[1,2]); // this指向windowfn.apply(undefined,[1,2]); // this指向window

                call

                call方法的第一個(gè)參數(shù)也是this的指向,后面?zhèn)魅氲氖且粋€(gè)參數(shù)列表

                跟apply一樣,改變this指向后原函數(shù)會(huì)立即執(zhí)行,且此方法只是臨時(shí)改變this指向一次

                調(diào)用call的方式如下

                var foo = { value: 1};function bar(name, age) { console.log(name) console.log(age) console.log(this.value);}bar.call(foo, ‘kevin’, 18);// kevin// 18// 1

                有了call為什么還要apply呢,經(jīng)過(guò)一番查閱后,了解到使用call的速度比apply快,那疑惑就更嚴(yán)重了,apply還有存在的意義嗎?我們不妨假設(shè)當(dāng)需要傳入的參數(shù)很多時(shí),一般都是存放在數(shù)組中,如果只有call的話,就需要我們對(duì)數(shù)組做一些處理,轉(zhuǎn)換成參數(shù)列表的形式,但是使用apply的話就減輕了工作量,可以這樣認(rèn)為吧,apply時(shí)call的語(yǔ)法糖。(為什么參數(shù)多的時(shí)候會(huì)存放在數(shù)組里面捏?本孩認(rèn)為,數(shù)組可以被認(rèn)為一個(gè)整體,不易出現(xiàn)丟參的情況,而且數(shù)組有長(zhǎng)度,可以輕而易舉的知道到底有多少個(gè)參數(shù))

                function fn(…args){ console.log(this,args);}let obj = { myname:”張三”}fn.call(obj,1,2); // this會(huì)變成傳入的obj,傳入的參數(shù)必須是一個(gè)數(shù)組;fn(1,2) // this指向window

                同樣的,當(dāng)?shù)谝粋€(gè)參數(shù)為null、undefined的時(shí)候,默認(rèn)指向window(在瀏覽器中)

                fn.call(null,[1,2]); // this指向windowfn.call(undefined,[1,2]); // this指向window

                bind

                bind方法和call很相似,第一參數(shù)也是this的指向,后面?zhèn)魅氲囊彩且粋€(gè)參數(shù)列表(但是這個(gè)參數(shù)列表可以分多次傳入)

                改變this指向后不會(huì)立即執(zhí)行,而是返回一個(gè)永久改變this指向的函數(shù)

                var foo = {value: 1};function bar(name, age) {console.log(name)console.log(age)console.log(this.value);}bar.bind(foo, ‘kevin’, 18);// 沒(méi)有任何輸出

                為什么會(huì)沒(méi)有輸出呢?上文已經(jīng)提到了,這就是和bind、call的區(qū)別了

                bind不會(huì)執(zhí)行bar函數(shù),只是改變了其this指向,并且給它傳入了參數(shù),添加一行代碼呢?如下:

                var foo = {value: 1};function bar(name, age) {console.log(name)console.log(age)console.log(this.value);}bar.bind(foo, ‘kevin’, 18);bar();// undefined// undefined// undefined

                對(duì)的,你沒(méi)看錯(cuò),輸出了三個(gè)undefined,因?yàn)殡m然調(diào)用了bar(),但this指向了window且沒(méi)有傳入任何參數(shù),理所當(dāng)然都是undefined了,可見(jiàn)使用了bind后并不會(huì)改變?cè)瘮?shù),其實(shí)call和apply也都不會(huì)改變?cè)瓍?shù),也就是說(shuō)call和apply是一次性的,這里為什么我沒(méi)說(shuō)bind呢,因?yàn)樗麜?huì)返回一個(gè)函數(shù),如果我們保存這個(gè)函數(shù),它就不是一次性的了,如果再執(zhí)行這個(gè)函數(shù)就可以達(dá)到我們想要的效果了,注意:執(zhí)行apply和call時(shí),就如同執(zhí)行原函數(shù),返回值和原函數(shù)相同,如果原函數(shù)不返回值,則apply和call也不會(huì)返回任何值!

                function fn(…args){ console.log(this,args);}let obj = { myname:”張三”}const bindFn = fn.bind(obj); // this 也會(huì)變成傳入的obj ,bind不是立即執(zhí)行需要執(zhí)行一次bindFn(1,2) // this指向objfn(1,2) // this指向window

                小結(jié)

                從上面可以看到,apply、call、bind三者的區(qū)別在于:

                • 三者都可以改變函數(shù)的this對(duì)象指向
                • 三者第一個(gè)參數(shù)都是this要指向的對(duì)象,如果如果沒(méi)有這個(gè)參數(shù)或參數(shù)為undefined或null,則默認(rèn)指向全局window
                • 三者都可以傳參,但是apply是數(shù)組,而call是參數(shù)列表,且apply和call是一次性傳入?yún)?shù),而bind可以分為多次傳入
                • bind是返回綁定this之后的函數(shù),apply、call 則是立即執(zhí)行

                實(shí)現(xiàn)

                實(shí)現(xiàn)bind的步驟,我們可以分解成為三部分:

                • 修改this指向
                • 動(dòng)態(tài)傳遞參數(shù)

                // 方式一:只在bind中傳遞函數(shù)參數(shù)fn.bind(obj,1,2)()// 方式二:在bind中傳遞函數(shù)參數(shù),也在返回函數(shù)中傳遞參數(shù)fn.bind(obj,1)(2)

                • 兼容new關(guān)鍵字

                整體實(shí)現(xiàn)代碼如下:

                Function.prototype.myBind = function (context) { // 判斷調(diào)用對(duì)象是否為函數(shù) if (typeof this !== “function”) { throw new TypeError(“Error”); } // 獲取參數(shù) const args = […arguments].slice(1), fn = this; return function Fn() { // 根據(jù)調(diào)用方式,傳入不同綁定值 return fn.apply(this instanceof Fn ? new fn(…arguments) : context, args.concat(…arguments)); }}

                給大家分享我收集整理的各種學(xué)習(xí)資料,前端小白交學(xué)習(xí)流程,入門(mén)教程等回答-下面是學(xué)習(xí)資料參考。

                前端學(xué)習(xí)交流、自學(xué)、學(xué)習(xí)資料等推薦 – 知乎

                鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶(hù)投稿
                上一篇 2022年7月7日 09:21
                下一篇 2022年7月7日 09:21

                相關(guān)推薦

                • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應(yīng)該怎么發(fā))

                  對(duì)于微商朋友來(lái)說(shuō),朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經(jīng)營(yíng)一個(gè)朋友圈,有的微商看起來(lái)逼格滿滿,實(shí)際效果也不錯(cuò);而有的卻動(dòng)都不動(dòng)就被屏蔽甚至拉黑…

                  2022年11月27日
                • 存儲(chǔ)過(guò)程語(yǔ)法(sql server存儲(chǔ)過(guò)程語(yǔ)法)

                  今天小編給各位分享存儲(chǔ)過(guò)程語(yǔ)法的知識(shí),其中也會(huì)對(duì)sql server存儲(chǔ)過(guò)程語(yǔ)法進(jìn)行解釋?zhuān)绻芘銮山鉀Q你現(xiàn)在面臨的問(wèn)題,別忘了關(guān)注本站,現(xiàn)在開(kāi)始吧! oracle存儲(chǔ)過(guò)程基本語(yǔ)法…

                  2022年11月26日
                • 《寶可夢(mèng)朱紫》夢(mèng)特性怎么獲得?隱藏特性獲取方法推薦

                  寶可夢(mèng)朱紫里有很多寶可夢(mèng)都是擁有夢(mèng)特性會(huì)變強(qiáng)的寶可夢(mèng),很多玩家不知道夢(mèng)特性怎么獲得,下面就給大家?guī)?lái)寶可夢(mèng)朱紫隱藏特性獲取方法推薦,感興趣的小伙伴一起來(lái)看看吧,希望能幫助到大家。 …

                  2022年11月25日
                • 《寶可夢(mèng)朱紫》奇魯莉安怎么進(jìn)化?奇魯莉安進(jìn)化方法分享

                  寶可夢(mèng)朱紫中的奇魯莉安要怎么進(jìn)化呢?很多玩家都不知道,下面就給大家?guī)?lái)寶可夢(mèng)朱紫奇魯莉安進(jìn)化方法分享,感興趣的小伙伴一起來(lái)看看吧,希望能幫助到大家。 奇魯莉安進(jìn)化方法分享 奇魯莉安…

                  2022年11月25日
                • 淘寶直播平臺(tái)抽成多少(淘寶直播平臺(tái)抽成比例)

                  隨著時(shí)代的發(fā)展,現(xiàn)在直播帶貨已經(jīng)成為主要帶貨方式,其中淘寶是主流帶貨平臺(tái),不少人在上面直播帶貨賺錢(qián),一些小伙伴也想加入,那么淘寶直播平臺(tái)抽成多少?下面小編為大家?guī)?lái)淘寶直播平臺(tái)抽成…

                  2022年11月24日
                • 銳龍97900x參數(shù)規(guī)格跑分評(píng)測(cè) 銳龍97900x屬于什么檔次

                  銳龍9 7900X是銳龍7000系列處理器中性能頂尖的型號(hào)之一,它采用了這一代標(biāo)配的zen4架構(gòu)和5nm制程工藝,那么它具體的參數(shù)跑分如何,在電腦上世紀(jì)發(fā)揮怎么樣呢,下面就來(lái)看看銳…

                  2022年11月24日
                • 白襯衫搭配什么褲子好看,女生襯衫穿法圖片

                  說(shuō)起白襯衫和長(zhǎng)褲的搭配組合,不知道大家有沒(méi)有發(fā)現(xiàn),雖然是很常見(jiàn)的造型,可不同年齡段慣用的穿搭方式卻不相同,從而也穿出了不同的味道。簡(jiǎn)直是現(xiàn)在這個(gè)季節(jié),時(shí)髦精們的必備造型之一~ 70…

                  2022年11月24日
                • 《寶可夢(mèng)朱紫》暴飛龍?jiān)趺醋ィ勘╋w龍獲得方法

                  寶可夢(mèng)朱紫暴飛龍位置在哪?在游戲中,很多玩家還不清楚暴飛龍具體要怎么樣獲得,其實(shí)獲得方法很簡(jiǎn)單,暴飛龍直接是沒(méi)得抓的,需要玩家從寶貝龍進(jìn)化得到,下面一起來(lái)看一下寶可夢(mèng)朱紫暴飛龍獲得…

                  2022年11月23日
                • 《寶可夢(mèng)朱紫》布土撥怎么進(jìn)化?布土撥進(jìn)化方法介紹

                  寶可夢(mèng)朱紫中,不同的寶可夢(mèng)有不同的進(jìn)化方法,其中布土撥的進(jìn)化方法是比較特殊的。很多玩家不知道寶可夢(mèng)朱紫布土撥怎么進(jìn)化,下面就帶來(lái)寶可夢(mèng)朱紫布土撥進(jìn)化方法介紹,一起來(lái)看看吧,希望能幫…

                  2022年11月23日
                • 《寶可夢(mèng)朱紫》薄荷怎么獲得?薄荷獲得方法

                  寶可夢(mèng)朱紫中薄荷有改變寶可夢(mèng)的屬性或性格等效果,很多玩家想知道寶可夢(mèng)朱紫薄荷怎么獲得,下面就帶來(lái)寶可夢(mèng)朱紫薄荷獲得方法,感興趣的小伙伴一起來(lái)看看吧,希望能幫助到大家。 薄荷獲得方法…

                  2022年11月23日

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息