JS前端面試題詳解之手寫bind
大家好,我是前端西瓜哥,今天我們用 JS 來實(shí)現(xiàn)內(nèi)置的 bind 方法。
bind 的用法
在實(shí)現(xiàn)之前,我們先學(xué)習(xí)一下 Function.prototype.bind 的用法。
function.bind(thisArg[, arg1[, arg2[, ...]]])
bind 是函數(shù)特有的一個方法,可以創(chuàng)建一個綁定了 this 的新函數(shù)。
接受的參數(shù)為如下。
- 第 1 個參數(shù) thisArg:用于修改 this 指向,且 this 一旦修改后將無法再改變。
- arg1, arg2, ...:剩余的是可選的參數(shù)項(xiàng),會在 bind 返回的新函數(shù)調(diào)用時,會作為函數(shù)的前幾個參數(shù)去調(diào)用。
this 的指向問題
我們在開發(fā)的時候,有時候會遇到 JS 的 this 指向丟失問題。
下面我們看一個例子。
const person = { nickname: '前端西瓜哥', eatWatermelon() { console.log(this.nickname + ' 吃西瓜'); } }; person.eatWatermelon();
上面的代碼中,在調(diào)用 person.eatWatermelon 時,this 指向 person,輸入結(jié)果為 前端西瓜哥 吃西瓜。
下面我們再執(zhí)行下面代碼。
const eatWatermelon = person.eatWatermelon; eatWatermelon();
輸入結(jié)果就匪夷所思了起來,它是:undefined 吃西瓜
這是因?yàn)?this 的指向變成了 eatWatermelon()
執(zhí)行時所在作用域的 this,在瀏覽器 script 標(biāo)簽最外層時,是全局對象 window(嚴(yán)格模式下,全局對象 this 會變成 undefined)。
所以 eatWatermelon()
執(zhí)行中的 this.nickname 等價于 window.nickname,因?yàn)槲覀儧]有賦值過,所以是 undefined。
有時候我們不希望 this 丟失,該怎么辦?
這時候我們就要用到一個 bind 方法,可以永久改變 this 的指向,且不能再改變。
const eatWatermelon = person.eatWatermelon.bind(person); eatWatermelon();
這樣的話,eatWatermelon 函數(shù)的 this 就會永遠(yuǎn)指向 person,能輸出我們預(yù)期的 前端西瓜哥 吃西瓜。
所以,對于一個函數(shù)來說,它的 this 指向是在執(zhí)行時確定的:
- 如果函數(shù)是 bind 返回的,this 永遠(yuǎn)指向執(zhí)行 bind 綁定的那個 thisArg 值;
- 如果函數(shù)前面有個對象,那 this 指向這個對象;
- 如果函數(shù)前沒有對象,那 this 指向當(dāng)前的作用域(可能是函數(shù)作用域,可能是全局作用域)。
另一種控制 this 指向的寫法是使用 箭頭函數(shù),尤其適合在函數(shù)中調(diào)用另一個函數(shù)的情況,因?yàn)槠蜻@里不展開講。
積累參數(shù)
bind 除了常用于強(qiáng)綁 this 外,另一個用的比較少的作用:預(yù)置函數(shù)參數(shù)。
function add(a, b, c) { return a + b + c; } const addSix = add.bind(null, 6); const addSixThenAddFour = addSix.bind(null, 4); addSixThenAddFour(5) // 15 addSixThenAddFour(7) // 17
實(shí)現(xiàn)一個 bind
下面進(jìn)入正題,實(shí)現(xiàn)一個 bind。
Function.prototype.myBind = function(thisArg, ...prefixArgs) { const fn = this; return function(...args) { return fn.call(thisArg, ...prefixArgs, ...args); } }
要點(diǎn)是利用 閉包。
讓返回的新函數(shù)可以訪問到三個私有屬性:
- fn(原來的函數(shù))
- thisArg(需要強(qiáng)綁不變的 this 指向)
- prefixArgs 屬性
當(dāng)我們調(diào)用這個新函數(shù)時,我們會執(zhí)行 fn 函數(shù),并利用 call 方法來指定 this 為 thisArg,然后將預(yù)填充的多個參數(shù),和新函數(shù)接收的參數(shù)依次填入。
最后不要忘記返回調(diào)用后的值。因?yàn)樾潞瘮?shù)是原函數(shù)的封裝,返回值也要和原函數(shù)表現(xiàn)一致。
結(jié)尾
bind 方法的實(shí)現(xiàn)并不復(fù)雜,更重要的是你要先掌握好 bind 的用法。
就好比做業(yè)務(wù)需求一樣,不明確需求,就容易產(chǎn)生 bug,
然后需要你對閉包有一定的認(rèn)識,知道如何去保存私有變量,以及封裝函數(shù)的寫法(記得 return 原函數(shù)的返回值)。
到此這篇關(guān)于JS前端面試題詳解之手寫bind的文章就介紹到這了,更多相關(guān)JS手寫bind內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
利用Vconsole和Fillder進(jìn)行移動端抓包調(diào)試方法
這篇文章主要介紹了利用Vconsole和Fillder進(jìn)行移動端抓包調(diào)試,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-03-03JS實(shí)現(xiàn)勻加速與勻減速運(yùn)動的方法示例
這篇文章主要介紹了JS實(shí)現(xiàn)勻加速與勻減速運(yùn)動的方法,涉及javascript結(jié)合時間函數(shù)與數(shù)學(xué)運(yùn)算動態(tài)操作頁面元素樣式的相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下2017-09-09arcgis for js柵格圖層疊加(Raster Layer)問題
這篇文章主要介紹了arcgis for js柵格圖層疊加(Raster Layer)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11Javascript將雙字節(jié)字符轉(zhuǎn)換成單字節(jié)字符并計(jì)算長度
這篇文章主要介紹Javascript將雙字節(jié)字符轉(zhuǎn)換成單字節(jié)字符并計(jì)算長度的方法,簡單實(shí)用,需要的朋友可以參考下。2016-06-06JS集成fckeditor及判斷內(nèi)容是否為空的方法
這篇文章主要介紹了JS集成fckeditor及判斷內(nèi)容是否為空的方法,涉及fckeditor的設(shè)置及頁面元素的操作技巧,并分析了php環(huán)境下配置文件上傳的注意事項(xiàng),需要的朋友可以參考下2016-05-05用JavaScript實(shí)現(xiàn)讓瀏覽器停止載入頁面的方法
下面小編就為大家?guī)硪黄肑avaScript實(shí)現(xiàn)讓瀏覽器停止載入頁面的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01你必須知道的Javascript知識點(diǎn)之"字面量和對應(yīng)類型"說明介紹
本篇文章小編為大家介紹,你必須知道的Javascript知識點(diǎn)之"字面量和對應(yīng)類型"。需要的朋友參考下2013-04-04分享Javascript中最常用的55個經(jīng)典小技巧
這篇文章主要介紹了Javascript中最常用的55個經(jīng)典小技巧。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11