1、什么是bind
bind()方法創(chuàng)建一個新的函數(shù) ,在bind()被調(diào)用時,這個新函數(shù)的this被指定 bind()的第一個參數(shù),而其余參數(shù)將作為新函數(shù)的參數(shù),供調(diào)用時使用。
2、bind的語法
語法:
function.bind(thisArg[, arg1[, arg2[, ...]]])
參數(shù):
- thisArg :被綁定到函數(shù)上的對象,即當調(diào)用綁定后的函數(shù)時,函數(shù)中的
this關鍵字會指向該對象。如果thisArg參數(shù)為null或undefined,則this關鍵字將指向全局對象(在瀏覽器中通常是window對象)。 - arg1, arg2 :要傳遞給函數(shù)的參數(shù)。這些參數(shù)將按照順序傳遞給函數(shù),并在調(diào)用函數(shù)時作為函數(shù)參數(shù)使用。
返回值:
返回一個 原函數(shù)的拷貝 ,并擁有指定的this值和初始參數(shù)。
3、淺試一下bind
代碼:
this.name = 'guizimo'
let obj = {
name: 'zimo',
getName: function() {return this.name}
}
console.log(obj.getName()) // zimo
let newGetName = obj.getName
console.log(newGetName()) // guizimo
let bindGetName = newGetName.bind(obj)
console.log(bindGetName()) // zimo
簡述代碼:
- 第一次打印
zimo,可以理解為是打印對象內(nèi)的一個屬性,此時的this是指向obj對象。 - 第二次打印
guizimo,因為當前環(huán)境是對象外,因為當前執(zhí)行的函數(shù)是newGetName(),因此函數(shù)內(nèi)部的this指向全局對象。 - 通過
bind生成一個 新的拷貝函數(shù) ,當前執(zhí)行的函數(shù)bindGetName()的this指向obj對象。
4、手寫bind
這是面試官最喜歡的環(huán)節(jié)了
思路:
bind()方法返回一個新函數(shù),因此需要定義一個函數(shù)來返回新函數(shù)。- 在新函數(shù)中,需要使用
apply()或call()方法來調(diào)用原始函數(shù)并傳遞正確的this值和參數(shù)。 - 新函數(shù)需要接受一個
thisArg參數(shù)來指定要綁定的對象,并可以接受任意數(shù)量的其他參數(shù)。
代碼:
/**
* 手寫bind
* @returns {function(): any}
*/
Function.prototype.myBind = function () {
// 處理函數(shù)
let args = Array.from(arguments);
let thisArg = args.shift();
// 暫存this
let thisFunc = this;
// 因為需要構(gòu)造函數(shù),所以不能是匿名函數(shù)了
const fBound = function () {
const newArgs = args.concat(Array.from(arguments));
// 判斷是否為構(gòu)造函數(shù)
thisArg = this instanceof fBound ? this : thisArg;
return thisFunc.apply(thisArg, newArgs);
}
// 直接將原函數(shù)的prototype賦值給綁定函數(shù)
fBound.prototype = this.prototype;
// 返回
return fBound;
}
簡述代碼:
- 通過
Array.from()將arguments轉(zhuǎn)化為數(shù)組對象,通過shift()取出thisArg。 - 使用
thisFunc暫存當前函數(shù)的this。 - 創(chuàng)建一個閉包函數(shù)
fBound,newArgs接收合并處理的arguments。 - 判斷
fBound是否為構(gòu)造函數(shù),如果是構(gòu)造函數(shù),返回閉包的this,反之,返回外部拿到的thisArg,使用thisArg來接收。 - 使用
thisFunc.apply傳遞thisArg值和參數(shù)newArgs。 - 直接將原函數(shù)的
prototype賦值給fBound。 - 返回
fBound。
5、使用場景
5.1、創(chuàng)建綁定函數(shù)
這是bind最基本的一種使用方式了,也就是 創(chuàng)建一個新的函數(shù) 。
代碼:
this.name = 'guizimo'
let obj = {
name: 'zimo',
getName: function() {return this.name}
}
console.log(obj.getName()) // zimo
let newGetName = obj.getName
console.log(newGetName()) // guizimo
let bindGetName = newGetName.bind(obj)
console.log(bindGetName()) // zimo
簡述代碼:
- 第一次打印
zimo,可以理解為是打印對象內(nèi)的一個屬性,此時的this是指向obj對象。 - 第二次打印
guizimo,因為當前環(huán)境是對象外,因為當前執(zhí)行的函數(shù)是newGetName(),因此函數(shù)內(nèi)部的this指向全局對象。 - 通過
bind生成一個 新的拷貝函數(shù) ,當前執(zhí)行的函數(shù)bindGetName()的this指向obj對象。
5.2、創(chuàng)建偏函數(shù)
如果需要創(chuàng)建一個自定義函數(shù),需要固定部分參數(shù),那么bind就有它獨特的作用了
代碼:
function add (a, b) {
return a + b
}
const res1 = add(1, 2)
console.log(res1) // 3
// 創(chuàng)建一個偏函數(shù),將1作為預設的參數(shù)
const addP = add.bind(null, 1)
const res2 = addP(2)
console.log(res2) // 3
const res3 = addP(3)
console.log(res3) // 4
const res4 = addP(4)
console.log(res4) // 5
簡述代碼:
- 創(chuàng)建了一個
add函數(shù),調(diào)用add(1, 2),正常打印3。 - 創(chuàng)建一個偏函數(shù)
addP,將1作為預設的參數(shù),調(diào)用addP(2),也可以正常打印3,后續(xù)調(diào)用addP(3)、addp(4),皆打印正確的數(shù)值, 實現(xiàn)了對一個參數(shù)的固定 。
6、在工作中有遇到bind的使用場景嗎
6.1、React中bind的場景
在JSX中傳遞的事件不是一個字符串,而是一個函數(shù)(如:onClick={this.handleClick}),此時onClick即是中間變量,所以處理函數(shù)中的this指向會丟失。
代碼:
this< /span?>.handleClick.bind(this)} >點擊< /button >
//此時this指向是當前實例對象
handleAdd = () = > {
console.log(this)
this.setState({
...
})
}
解決這個問題就是給調(diào)用函數(shù)時bind(this),從而使得無論事件處理函數(shù)如何傳遞,this指向都是當前實例化對象。或者 使用箭頭函數(shù)聲明一個函數(shù) ,這樣函數(shù)內(nèi)的this也是指向當前實例。
6.2、在事件處理程序中訪問事件目標的this值
在JavaScript中,需要在事件處理程序中訪問事件目標的this值。在這種情況下,可以使用bind()方法將事件處理程序綁定到事件目標上,以便在調(diào)用事件處理程序時,this關鍵字始終指向事件目標。
代碼:
const button = document.querySelector('#myButton');
button.addEventListener('click', function() {
// 在這里可以使用 this 訪問按鈕元素的屬性和方法
}.bind(button));
-
處理器
+關注
關注
68文章
20143瀏覽量
246657 -
JAVA語言
+關注
關注
0文章
138瀏覽量
21340 -
javascript
+關注
關注
0文章
525瀏覽量
55967
發(fā)布評論請先 登錄
udp_bind這個綁定的端口怎么解除?
TCP/IP棧使用bind函數(shù)綁定IP地址和端口失敗的原因?
仿真軟件proteus報錯“ VDM server failed to bind port 8000”
TCP server 不能 bind 80 端口?
TCPIP_UDP_Bind()阻止udp客戶端發(fā)送UDP數(shù)據(jù)包
將CC3000做服務端,為什么bind總是返回-1?
linux中的busybox,是否帶有bind和ifenslave?
用telnet組件提示bind socket failed是什么原因?
Bind源代碼包安裝
SystemVerilog中bind用法總結(jié)+送實驗源碼和腳本
bind系統(tǒng)調(diào)用背后的端口管理復用

什么是bind?你真的熟悉bind嗎?
評論