翼度科技»论坛 编程开发 JavaScript 查看内容

【JavaScript】你真的熟悉bind吗

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21

引言

内容速递

看了本文您能了解到的知识!
在本篇文章中,将带你了解什么是bindbind的用途如何手写bind以及工作中实际使用bind的场景
在JavaScript中,bind()方法是用来创建一个新函数,并将其绑定到指定的对象上,从而在调用该函数时确保函数中的this关键字指向绑定的对象。
1、什么是bind

bind()方法创建一个新的函数,在bind()被调用时,这个新函数的this被指定 bind()的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
MDN文档Function.prototype.bind()
2、bind的语法

语法:
  1. function.bind(thisArg[, arg1[, arg2[, ...]]])
复制代码
参数:

  • thisArg:被绑定到函数上的对象,即当调用绑定后的函数时,函数中的this关键字会指向该对象。如果thisArg参数为null或undefined,则this关键字将指向全局对象(在浏览器中通常是window对象)。
  • arg1, arg2, ...:要传递给函数的参数。这些参数将按照顺序传递给函数,并在调用函数时作为函数参数使用。
返回值:
返回一个原函数的拷贝,并拥有指定的this值和初始参数。
3、浅试一下bind

代码:
  1. this.name = 'guizimo'
  2. let obj = {
  3.   name: 'zimo',
  4.   getName: function() {return this.name}
  5. }
  6. console.log(obj.getName())    // zimo
  7. let newGetName = obj.getName
  8. console.log(newGetName())     // guizimo
  9. let bindGetName = newGetName.bind(obj)
  10. console.log(bindGetName())     // zimo
复制代码
简述代码:

  • 第一次打印zimo,可以理解为是打印对象内的一个属性,此时的this是指向obj对象。
  • 第二次打印guizimo,因为当前环境是对象外,因为当前执行的函数是newGetName(),因此函数内部的this指向全局对象。
  • 通过bind生成一个新的拷贝函数,当前执行的函数bindGetName()的this指向obj对象。
4、手写bind

这是面试官最喜欢的环节了
思路:

  • bind()方法返回一个新函数,因此需要定义一个函数来返回新函数。
  • 在新函数中,需要使用apply()或call()方法来调用原始函数并传递正确的this值和参数。
  • 新函数需要接受一个thisArg参数来指定要绑定的对象,并可以接受任意数量的其他参数。
代码:
  1. /**
  2. * 手写bind
  3. * @returns {function(): any}
  4. */
  5. Function.prototype.myBind = function () {
  6.   // 处理函数
  7.   let args = Array.from(arguments);
  8.   let thisArg = args.shift();
  9.   // 暂存this
  10.   let thisFunc = this;
  11.   // 因为需要构造函数,所以不能是匿名函数了
  12.   const fBound = function () {
  13.     const newArgs = args.concat(Array.from(arguments));
  14.     // 判断是否为构造函数
  15.     thisArg = this instanceof fBound ? this : thisArg;
  16.     return thisFunc.apply(thisArg, newArgs);
  17.   }
  18.   // 直接将原函数的prototype赋值给绑定函数
  19.   fBound.prototype = this.prototype;
  20.   // 返回
  21.   return fBound;
  22. }
复制代码
简述代码:

  • 通过Array.from()将arguments转化为数组对象,通过shift()取出thisArg。
  • 使用thisFunc暂存当前函数的this。
  • 创建一个闭包函数fBound,newArgs接收合并处理的arguments。
  • 判断fBound是否为构造函数,如果是构造函数,返回闭包的this,反之,返回外部拿到的thisArg,使用thisArg来接收。
  • 使用thisFunc.apply传递thisArg值和参数newArgs。
  • 直接将原函数的prototype赋值给fBound。
  • 返回fBound。
5、使用场景

5.1、创建绑定函数

这是bind最基本的一种使用方式了,也就是创建一个新的函数
代码:
  1. this.name = 'guizimo'
  2. let obj = {
  3.   name: 'zimo',
  4.   getName: function() {return this.name}
  5. }
  6. console.log(obj.getName())    // zimo
  7. let newGetName = obj.getName
  8. console.log(newGetName())     // guizimo
  9. let bindGetName = newGetName.bind(obj)
  10. console.log(bindGetName())     // zimo
复制代码
简述代码:

  • 第一次打印zimo,可以理解为是打印对象内的一个属性,此时的this是指向obj对象。
  • 第二次打印guizimo,因为当前环境是对象外,因为当前执行的函数是newGetName(),因此函数内部的this指向全局对象。
  • 通过bind生成一个新的拷贝函数,当前执行的函数bindGetName()的this指向obj对象。
5.2、创建偏函数

如果需要创建一个自定义函数,需要固定部分参数,那么bind就有它独特的作用了
代码:
  1. function add (a, b) {
  2.   return a + b
  3. }
  4. const res1 = add(1, 2)
  5. console.log(res1)  // 3
  6. // 创建一个偏函数,将1作为预设的参数
  7. const addP = add.bind(null, 1)
  8. const res2 = addP(2)
  9. console.log(res2)  // 3
  10. const res3 = addP(3)
  11. console.log(res3)  // 4
  12. const res4 = addP(4)
  13. console.log(res4)  // 5
复制代码
简述代码:

  • 创建了一个add 函数,调用add(1, 2),正常打印3。
  • 创建一个偏函数addP,将1作为预设的参数,调用addP(2),也可以正常打印3,后续调用addP(3)、addp(4),皆打印正确的数值,实现了对一个参数的固定
6、在工作中有遇到bind的使用场景吗

6.1、React中bind的场景

在JSX中传递的事件不是一个字符串,而是一个函数(如:onClick={this.handleClick}),此时onClick即是中间变量,所以处理函数中的this指向会丢失。
代码:
  1. <button onClick={this.handleClick.bind(this)}>点击</button>
  2. //此时this指向是当前实例对象
  3. handleAdd = () => {
  4.     console.log(this)
  5.     this.setState({
  6.         ...
  7.     })
  8. }
复制代码
解决这个问题就是给调用函数时bind(this),从而使得无论事件处理函数如何传递,this指向都是当前实例化对象。或者使用箭头函数声明一个函数,这样函数内的this也是指向当前实例。
6.2、在事件处理程序中访问事件目标的this值

在JavaScript中,需要在事件处理程序中访问事件目标的this值。在这种情况下,可以使用bind()方法将事件处理程序绑定到事件目标上,以便在调用事件处理程序时,this关键字始终指向事件目标。
代码:
  1. const button = document.querySelector('#myButton');
  2. button.addEventListener('click', function() {
  3.   // 在这里可以使用 this 访问按钮元素的属性和方法
  4. }.bind(button));
复制代码
博客说明与致谢

文章所涉及的部分资料来自互联网整理,其中包含自己个人的总结和看法,分享的目的在于共建社区和巩固自己。
引用的资料如有侵权,请联系本人删除!
感谢勤劳的自己个人博客GitHub,公众号【归子莫】,小程序【子莫说】
如果你感觉对你有帮助的话,不妨给我点赞鼓励一下,好文记得收藏哟!
幸好我在,感谢你来!

来源:https://www.cnblogs.com/guizimo/p/17554145.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具