首页 > 编程语言 >【JavaScript】你真的熟悉bind吗

【JavaScript】你真的熟悉bind吗

时间:2023-07-14 16:45:13浏览次数:57  
标签:obj 函数 bind JavaScript 熟悉 thisArg console log

你真的了解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,公众号【归子莫】,小程序【子莫说】

如果你感觉对你有帮助的话,不妨给我点赞鼓励一下,好文记得收藏哟!

幸好我在,感谢你来!

标签:obj,函数,bind,JavaScript,熟悉,thisArg,console,log
From: https://www.cnblogs.com/guizimo/p/17554145.html

相关文章

  • 【JavaScript】js 处理复制函数实现
    exportconstcopyText=(text:string)=>{constinput=document.createElement('input');input.setAttribute('readonly','readonly');input.setAttribute('value',text);document.body.appendChild(input);......
  • ASP.NET Core SignalR 系列(三)- JavaScript 客户端
    本章将和大家分享ASP.NETCoreSignalR中的JavaScript客户端。ASP.NETCoreSignalRJavaScript客户端库使开发人员能够调用服务器端SignalR中心代码。本文大部分内容摘自微软官网:https://learn.microsoft.com/zh-cn/aspnet/core/signalr/javascript-client?view=aspnetcore......
  • 2023-07-13:如果你熟悉 Shell 编程,那么一定了解过花括号展开,它可以用来生成任意字符串
    2023-07-13:如果你熟悉Shell编程,那么一定了解过花括号展开,它可以用来生成任意字符串。花括号展开的表达式可以看作一个由花括号、逗号和小写英文字母组成的字符串定义下面几条语法规则:如果只给出单一的元素x,那么表达式表示的字符串就只有"x"。R(x)={x}例如,表达式"a"......
  • JavaScript 中获取数组最后一个元素3种方法及性能
    当需要从JavaScript中的数组中获取最后一个元素时,有多种选择,本文将提供3种可用方法。1.数组length属性length属性返回数组中元素的数量。从数组的长度中减去1得到数组最后一个元素的索引,使用它可以访问最后一个元素。从长度中减去1的原因是,在JavaScript中,数组索引......
  • JavaScript
    引入JavaScript1.内部标签<script></script>2.外部引用<scriptsrc="引入JavaScript.js"></script>浏览器控制台使用1.alert(弹窗)alert();2.console.log(控制台打印)console.log();数据类型1.等于和绝对等于==等于(类型不一样,值相等,判断为true)===绝......
  • 如何掌握JavaScript面向对象开发相关模式?
    本文学习目标:理解面向对象开发思想掌握JavaSciprt面向对象开发模式不管是JavaScript高级还是针对JavaScript语言本身的一个进阶学习,在开始之前我们先来对JavaScript相关知识点做一个回顾总结。一、JavaScript是什么1.1解析执行:轻量级解释型的语言特点:动态、头等函数(First-classFu......
  • JMeter脚本报错:Cannot find engine named: 'javascript'的解决方法
    本文将介绍如何解决在JMeter版本5.4.1下执行脚本时出现的错误信息“javax.script.ScriptException:Cannotfindenginenamed:'javascript'”。通过将本地JDK版本从18.0.1.1更改为1.8.0_151来解决此问题。当使用JMeter进行脚本执行时,有时可能会遇到以下错误信息:javax.script......
  • 你信不信,只要学几天javascript就可以使用纯原生实现五星评分效果 【附完整代码】
    ......
  • JavaScript 将对象数组按字母顺序排序
    原文链接:JavaScript将对象数组按字母顺序排序这里给出三种解决方案:1.if条件语句+sort()2.localeCompare()+sort()3.Collator()+sort()sort用法语法array.sort(compareFunction)参数值参数描述compareFunction可选。定义替代排序顺序的函数。该函数......
  • rust-bindgen报错 ‘Unable to find libclang的解决办法
    Windows下面可能会遇到这个问题的解决方案:1)把LLVM安装到没有空格的路径。2)LIBCLANG_PATH的值不要加双引号。thread'main'panickedat'Unabletofindlibclang:"couldn'tfindanyvalidsharedlibrariesmatching:['clang.dll','libclang.dll'],setth......