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 就會永遠指向 person,能輸出我們預(yù)期的 前端西瓜哥 吃西瓜。
所以,對于一個函數(shù)來說,它的 this 指向是在執(zhí)行時確定的:
- 如果函數(shù)是 bind 返回的,this 永遠指向執(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
下面進入正題,實現(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,
然后需要你對閉包有一定的認識,知道如何去保存私有變量,以及封裝函數(shù)的寫法(記得 return 原函數(shù)的返回值)。
到此這篇關(guān)于JS前端面試題詳解之手寫bind的文章就介紹到這了,更多相關(guān)JS手寫bind內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Bootstrap滾動監(jiān)聽組件scrollspy.js使用方法詳解
這篇文章主要為大家詳細介紹了Bootstrap滾動監(jiān)聽組件scrollspy.js的使用方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-07-07
IE6-IE9中tbody的innerHTML不能賦值的解決方法
這篇文章主要介紹了IE6-IE9中tbody的innerHTML不能賦值的解決方法,需要的朋友可以參考下2014-06-06
JavaScript網(wǎng)頁禁用屏蔽常用操作小結(jié)
這篇文章主要為大家詳細介紹了網(wǎng)頁前端常用的JavaScript屏蔽操作,包括網(wǎng)絡(luò)劫持、禁止復(fù)制、禁止按鍵、清除緩存記錄等,有需要的可以了解下2024-11-11
uniapp開發(fā)H5打包微信小程序樣式失效的完美解決方法
本文主要介紹了在使用uniapp開發(fā)H5頁面并打包成微信小程序時,可能會出現(xiàn)樣式失效的問題,并提供了解決方法,通過本文的學(xué)習(xí),讀者可以了解uniapp開發(fā)H5頁面打包成微信小程序的注意事項,避免出現(xiàn)樣式失效等問題2023-03-03
JS Testing Properties 判斷屬性是否在對象里的方法
下面小編就為大家?guī)硪黄狫S Testing Properties 判斷屬性是否在對象里的方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-10-10

