0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內(nèi)不再提示

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

冬至子 ? 來源:歸子莫 ? 作者:歸子莫 ? 2023-07-13 09:56 ? 次閱讀

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ù)為nullundefined,則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

簡述代碼:

  1. 第一次打印zimo,可以理解為是打印對象內(nèi)的一個屬性,此時的this是指向obj對象。
  2. 第二次打印guizimo,因為當前環(huán)境是對象外,因為當前執(zhí)行的函數(shù)是newGetName(),因此函數(shù)內(nèi)部的this指向全局對象。
  3. 通過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;
  // 因為需要構造函數(shù),所以不能是匿名函數(shù)了
  const fBound = function () {
    const newArgs = args.concat(Array.from(arguments));
    // 判斷是否為構造函數(shù)
    thisArg = this instanceof fBound ? this : thisArg;
    return thisFunc.apply(thisArg, newArgs);
  }
  // 直接將原函數(shù)的prototype賦值給綁定函數(shù)
  fBound.prototype = this.prototype;
  // 返回
  return fBound;
}

簡述代碼:

  1. 通過Array.from()arguments轉化為數(shù)組對象,通過shift()取出thisArg。
  2. 使用thisFunc暫存當前函數(shù)的this。
  3. 創(chuàng)建一個閉包函數(shù)fBound,newArgs接收合并處理的arguments
  4. 判斷fBound是否為構造函數(shù),如果是構造函數(shù),返回閉包的this,反之,返回外部拿到的thisArg,使用thisArg來接收。
  5. 使用thisFunc.apply傳遞thisArg值和參數(shù)newArgs。
  6. 直接將原函數(shù)的prototype賦值給fBound。
  7. 返回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

簡述代碼:

  1. 第一次打印zimo,可以理解為是打印對象內(nèi)的一個屬性,此時的this是指向obj對象
  2. 第二次打印guizimo,因為當前環(huán)境是對象外,因為當前執(zhí)行的函數(shù)是newGetName(),因此函數(shù)內(nèi)部的this指向全局對象。
  3. 通過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

簡述代碼:

  1. 創(chuàng)建了一個add 函數(shù),調(diào)用add(1, 2),正常打印3
  2. 創(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));
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權轉載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 處理器
    +關注

    關注

    68

    文章

    18927

    瀏覽量

    227248
  • JAVA語言
    +關注

    關注

    0

    文章

    138

    瀏覽量

    20027
  • javascript
    +關注

    關注

    0

    文章

    515

    瀏覽量

    53658
收藏 人收藏

    評論

    相關推薦

    從Linux源碼分析bind系統(tǒng)調(diào)用

    眾所周知,一個Server端Socket的建立,需要socket、bind、listen、accept四個步驟。
    的頭像 發(fā)表于 10-16 11:08 ?3124次閱讀
    從Linux源碼分析<b class='flag-5'>bind</b>系統(tǒng)調(diào)用

    udp_bind這個綁定的端口怎么解除?

    請教下,udp_bind 這個綁定的端口,剛開始是可以的,但是重新綁定時返回錯誤,有什么方法可以在 重新綁定前解除之前的綁定 ?
    發(fā)表于 04-22 07:41

    TCP/IP棧使用bind函數(shù)綁定IP地址和端口失敗的原因?

    TCP/IP 棧使用bind函數(shù)綁定IP地址和端口失??!softAP模式,TCPserver應用,客戶端連接以后IP地址和DNS地址還是原來的192.168.4.X。
    發(fā)表于 06-06 06:10

    仿真軟件proteus報錯“ VDM server failed to bind port 8000”

    本帖最后由 eehome 于 2013-1-5 10:07 編輯 每次啟動軟件都提示這個錯誤“ VDM server failed to bind port 8000”,并且不能與keil連機使用。這是什么問題???以前沒出現(xiàn)過這個問題。
    發(fā)表于 09-25 22:38

    TCP server 不能 bind 80 端口?

    后程序只開一個 AP 模式下的 TCP server ,測試。 ?但是發(fā)現(xiàn) 80 端口沒法 bind ,錯誤碼是 -98 ,意思是端口已被占用? 換一個其它端口號(比如 12345)就可以。 我們以后
    發(fā)表于 05-14 00:33

    TCPIP_UDP_Bind()阻止udp客戶端發(fā)送UDP數(shù)據(jù)包

    ;Starting connection\r\n");uint16_t local_port = 50728;if(!TCPIP_UDP_Bind(appData.clientSocket
    發(fā)表于 03-13 07:15

    bdb_find_bind怎樣配置才可以只作為target呢?

    按照如下方式啟動bdb_find_bind設備會作為target & initiator,怎樣配置才可以只作為target呢?bdb_SetIdentifyActiveEndpoint
    發(fā)表于 04-27 10:15

    將CC3000做服務端,為什么bind總是返回-1?

    CC3000作為客戶端的時候,是可以連接并傳輸數(shù)據(jù)的。當我將CC3000做服務端,BIND總是返回-1;調(diào)用socket,然后bind,結果返回-1,代碼如下: INT32 fd = socket
    發(fā)表于 06-15 12:45

    linux中的busybox,是否帶有bind和ifenslave?

    想問下,飛凌提供的linux中的busybox,是否帶有bind和ifenslave?如果沒有有什么辦法可以添加?
    發(fā)表于 01-11 06:53

    用telnet組件提示bind socket failed是什么原因?

    各位大佬,請教一下,我用F103加EC20的模塊,想開啟telnet的功能,我運行telnet_server后提示bind socket failed,如圖所示,在源代碼中也就是圖2的位置,請問
    發(fā)表于 05-11 10:08

    Bind源代碼包安裝

    先到官方下載Bind的安裝包 wgetftp://ftp.isc.org/isc/bind9/9.6.0-P1/bind-9.6.0-P1.tar.gz tar xzvf
    發(fā)表于 04-04 20:30 ?23次下載

    SystemVerilog中bind用法總結+送實驗源碼和腳本

    bind是systemverilog中一個重要的知識點,很多時候能夠在驗證中發(fā)揮重要的作用,今天就針對這個知識點做一個梳理,希望能幫助到大家。
    的頭像 發(fā)表于 01-11 08:59 ?8103次閱讀
    SystemVerilog中<b class='flag-5'>bind</b>用法總結+送實驗源碼和腳本

    bind系統(tǒng)調(diào)用背后的端口管理復用

    bind系統(tǒng)調(diào)用進行分析,主要是了解一下bind背后,Linux內(nèi)核是如何進行端口綁定、如何管理本地眾多的端口號。 先直觀感受bind系統(tǒng)調(diào)用背后的端口管理、端口復用 # include
    的頭像 發(fā)表于 07-31 10:45 ?465次閱讀
    <b class='flag-5'>bind</b>系統(tǒng)調(diào)用背后的端口管理復用

    Linux bind的核心執(zhí)行函數(shù)

    bind的核心執(zhí)行函數(shù) bind系統(tǒng)調(diào)用的核心函數(shù)調(diào)用流程如下: SYSCALL_DEFINE3( bind , int , fd, struct sockaddr __user
    的頭像 發(fā)表于 07-31 10:51 ?484次閱讀

    Linux內(nèi)核分析 bind端口選擇

    bind 傳 遞的地址參數(shù)中,port 字段為 0,那么就會自動選擇參數(shù)。 如代碼所示,當端口port沒有指定時,調(diào)用inet_csk_find_open_port(sk, port): if (!port) { head = inet_csk_
    的頭像 發(fā)表于 07-31 11:08 ?824次閱讀