【JavaScript】你真的熟悉bind嗎

来源:https://www.cnblogs.com/guizimo/archive/2023/07/14/17554145.html
-Advertisement-
Play Games

![你真的瞭解bind嗎](https://guizimo.oss-cn-shanghai.aliyuncs.com/img/%E4%BD%A0%E7%9C%9F%E7%9A%84%E4%BA%86%E8%A7%A3bind%E5%90%97.png) # 引言 ## 內容速遞 > 看了本文您能瞭解 ...


你真的瞭解bind嗎

引言

內容速遞

看了本文您能瞭解到的知識!

在本篇文章中,將帶你瞭解什麼是bindbind的用途如何手寫bind以及工作中實際使用bind的場景

在JavaScript中,bind()方法是用來創建一個新函數,並將其綁定到指定的對象上,從而在調用該函數時確保函數中的this關鍵字指向綁定的對象。

1、什麼是bind

bind()方法創建一個新的函數,在bind()被調用時,這個新函數的this被指定 bind()的第一個參數,而其餘參數將作為新函數的參數,供調用時使用。

MDN文檔Function.prototype.bind()

2、bind的語法

語法:

function.bind(thisArg[, arg1[, arg2[, ...]]])

參數:

  • thisArg:被綁定到函數上的對象,即當調用綁定後的函數時,函數中的this關鍵字會指向該對象。如果thisArg參數為nullundefined,則this關鍵字將指向全局對象(在瀏覽器中通常是window對象)。

  • arg1, arg2, ...:要傳遞給函數的參數。這些參數將按照順序傳遞給函數,併在調用函數時作為函數參數使用。

返回值:

返回一個原函數的拷貝,並擁有指定的this值和初始參數。

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,可以理解為是列印對象內的一個屬性,此時的this是指向obj對象

  2. 第二次列印guizimo,因為當前環境是對象外,因為當前執行的函數是newGetName(),因此函數內部的this指向全局對象。

  3. 通過bind生成一個新的拷貝函數,當前執行的函數bindGetName()this指向obj對象

4、手寫bind

這是面試官最喜歡的環節了

思路:

  • bind()方法返回一個新函數,因此需要定義一個函數來返回新函數。
  • 在新函數中,需要使用apply()call()方法來調用原始函數並傳遞正確的this值和參數。
  • 新函數需要接受一個thisArg參數來指定要綁定的對象,並可以接受任意數量的其他參數。

代碼:

/**
 * 手寫bind
 * @returns {function(): any}
 */
Function.prototype.myBind = function () {
  // 處理函數
  let args = Array.from(arguments);
  let thisArg = args.shift();
  // 暫存this
  let thisFunc = this;
  // 因為需要構造函數,所以不能是匿名函數了
  const fBound = function () {
    const newArgs = args.concat(Array.from(arguments));
    // 判斷是否為構造函數
    thisArg = this instanceof fBound ? this : thisArg;
    return thisFunc.apply(thisArg, newArgs);
  }
  // 直接將原函數的prototype賦值給綁定函數
  fBound.prototype = this.prototype;
  // 返回
  return fBound;
}

簡述代碼:

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

5、使用場景

5.1、創建綁定函數

這是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,可以理解為是列印對象內的一個屬性,此時的this是指向obj對象
  2. 第二次列印guizimo,因為當前環境是對象外,因為當前執行的函數是newGetName(),因此函數內部的this指向全局對象。
  3. 通過bind生成一個新的拷貝函數,當前執行的函數bindGetName()this指向obj對象

5.2、創建偏函數

如果需要創建一個自定義函數,需要固定部分參數,那麼bind就有它獨特的作用了

代碼:

function add (a, b) {
  return a + b
}

const res1 = add(1, 2)
console.log(res1)  // 3

// 創建一個偏函數,將1作為預設的參數
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. 創建了一個add 函數,調用add(1, 2),正常列印3
  2. 創建一個偏函數addP,將1作為預設的參數,調用addP(2),也可以正常列印3,後續調用addP(3)addp(4),皆列印正確的數值,實現了對一個參數的固定

6、在工作中有遇到bind的使用場景嗎

6.1、React中bind的場景

JSX中傳遞的事件不是一個字元串,而是一個函數(如:onClick={this.handleClick}),此時onClick即是中間變數,所以處理函數中的this指向會丟失。

代碼:

<button onClick={this.handleClick.bind(this)}>點擊</button>

//此時this指向是當前實例對象
handleAdd = () => {
    console.log(this)
    this.setState({
        ...
    })
}

解決這個問題就是給調用函數時bind(this),從而使得無論事件處理函數如何傳遞,this指向都是當前實例化對象。或者使用箭頭函數聲明一個函數,這樣函數內的this也是指向當前實例。

6.2、在事件處理程式中訪問事件目標的this值

在JavaScript中,需要在事件處理程式中訪問事件目標的this值。在這種情況下,可以使用bind()方法將事件處理程式綁定到事件目標上,以便在調用事件處理程式時,this關鍵字始終指向事件目標。

代碼:

const button = document.querySelector('#myButton');
button.addEventListener('click', function() {
  // 在這裡可以使用 this 訪問按鈕元素的屬性和方法
}.bind(button));

博客說明與致謝

文章所涉及的部分資料來自互聯網整理,其中包含自己個人的總結和看法,分享的目的在於共建社區和鞏固自己。

引用的資料如有侵權,請聯繫本人刪除!

感謝勤勞的自己個人博客GitHub,公眾號【歸子莫】,小程式【子莫說】

如果你感覺對你有幫助的話,不妨給我點贊鼓勵一下,好文記得收藏喲!

幸好我在,感謝你來!


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • # SQLServer 批量修改或插入 # 場景 今天在工作中遇到這麼一個場景,我需要根據條件對錶A做批量更新或插入。因為條件比較複雜,所以我使用了臨時表B,先把需要更新或插入的數據查詢出來放入臨時表。然後更新表A的某欄位,更新條件是A.id = B.id,更新效果是若記錄存在表A中,則更新表A的字 ...
  • ![file](https://img2023.cnblogs.com/other/2685289/202307/2685289-20230714100921932-1108940383.jpg) ## 用戶案例 | 自如 隨著自如業務的快速發展,不斷增長的調度任務和歷史逾萬的存量任務對平臺穩定性提 ...
  • MySQL資料庫遷移(直接複製文件) - 簡書 (jianshu.com) 看了幾種方法: 1、修改註冊表的 windows下遷移mysql數據 - 程式員丁先生 - 博客園 (cnblogs.com) 2、mysqldump指令將資料庫表/數據保存成xx.sql文件存到本地的 (157條消息) 如 ...
  • #### 先說些廢話 作為一個全棧開發工作者,曾經對公司專職的大數據開發有著濃厚的興趣,所以嘗試學習大數據開發所需要的各種技術棧。 本文就是我在學習過程中記錄下,所遇到的一些大數據面試的提問,僅供參考。 當然,因為時間精力有限,並非所有的問題我都去記錄了答案,如果您不瞭解某些問題或者不認可我記錄的解 ...
  • 1、簡介 人大金倉資料庫(KingbaseES)是面向事務處理類、兼顧分析類應用領域的新型資料庫產品,致力於解決高併發、高可靠數據存儲計算問題,是一款為企事業單位管理信息系統、業務系統量身打造的承載資料庫,目前性能已全面升級,是具有高成熟度的資料庫產品。 2、準備工作 資料庫的安裝包可以在人大金倉官 ...
  • ![](https://img2023.cnblogs.com/blog/3076680/202307/3076680-20230711162608661-1958587529.png) # 1. 一個季度的開始日期和結束日期 ## 1.1. 以yyyyq格式(前面4位是年份,最後1位是季度序號)給 ...
  • 原文地址:https://blog.csdn.net/zhanglei5415/article/details/131434931 ## 一、問題 當對含有中文的url字元串,進行NSURL對象包裝時,是不能被識別的。 不會得到期望的NSURL對象,而是返回一個nil 值 ; ```objectiv ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 本文的起因是有在代碼倉庫發包後,同事問我“為什麼package.json 里的版本還是原來的,有沒有更新?”,這個時候我意識到,我們完全沒有必要在每次發佈的時候還特意去關註這個倉庫的版本號,只要在發佈打tag的時候同步一下即可,於是有了本 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...