JS前端面試題詳解之手寫bind
大家好,我是前端西瓜哥,今天我們用 JS 來實現(xiàn)內(nèi)置的 bind 方法。
bind 的用法
在實現(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ù)項,會在 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 吃西瓜
這是因為 this 的指向變成了 eatWatermelon()
執(zhí)行時所在作用域的 this,在瀏覽器 script 標(biāo)簽最外層時,是全局對象 window(嚴(yán)格模式下,全局對象 this 會變成 undefined)。
所以 eatWatermelon()
執(zhí)行中的 this.nickname 等價于 window.nickname,因為我們沒有賦值過,所以是 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ù)的情況,因為篇幅原因這里不展開講。
積累參數(shù)
bind 除了常用于強綁 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
實現(xiàn)一個 bind
下面進(jìn)入正題,實現(xiàn)一個 bind。
Function.prototype.myBind = function(thisArg, ...prefixArgs) { const fn = this; return function(...args) { return fn.call(thisArg, ...prefixArgs, ...args); } }
要點是利用 閉包。
讓返回的新函數(shù)可以訪問到三個私有屬性:
- fn(原來的函數(shù))
- thisArg(需要強綁不變的 this 指向)
- prefixArgs 屬性
當(dāng)我們調(diào)用這個新函數(shù)時,我們會執(zhí)行 fn 函數(shù),并利用 call 方法來指定 this 為 thisArg,然后將預(yù)填充的多個參數(shù),和新函數(shù)接收的參數(shù)依次填入。
最后不要忘記返回調(diào)用后的值。因為新函數(shù)是原函數(shù)的封裝,返回值也要和原函數(shù)表現(xiàn)一致。
結(jié)尾
bind 方法的實現(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-03arcgis for js柵格圖層疊加(Raster Layer)問題
這篇文章主要介紹了arcgis for js柵格圖層疊加(Raster Layer)的相關(guān)資料,非常不錯,具有參考借鑒價值,需要的朋友可以參考下2017-11-11Javascript將雙字節(jié)字符轉(zhuǎn)換成單字節(jié)字符并計算長度
這篇文章主要介紹Javascript將雙字節(jié)字符轉(zhuǎn)換成單字節(jié)字符并計算長度的方法,簡單實用,需要的朋友可以參考下。2016-06-06JS集成fckeditor及判斷內(nèi)容是否為空的方法
這篇文章主要介紹了JS集成fckeditor及判斷內(nèi)容是否為空的方法,涉及fckeditor的設(shè)置及頁面元素的操作技巧,并分析了php環(huán)境下配置文件上傳的注意事項,需要的朋友可以參考下2016-05-05用JavaScript實現(xiàn)讓瀏覽器停止載入頁面的方法
下面小編就為大家?guī)硪黄肑avaScript實現(xiàn)讓瀏覽器停止載入頁面的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-01-01你必須知道的Javascript知識點之"字面量和對應(yīng)類型"說明介紹
本篇文章小編為大家介紹,你必須知道的Javascript知識點之"字面量和對應(yīng)類型"。需要的朋友參考下2013-04-04分享Javascript中最常用的55個經(jīng)典小技巧
這篇文章主要介紹了Javascript中最常用的55個經(jīng)典小技巧。需要的朋友可以過來參考下,希望對大家有所幫助2013-11-11