【JavaScript】你真的熟悉bind吗
引言
内容速递
看了本文您能了解到的知识!
在本篇文章中,将带你了解什么是bind,bind的用途、如何手写bind以及工作中实际使用bind的场景。
在JavaScript中,bind()
方法是用来创建一个新函数,并将其绑定到指定的对象上,从而在调用该函数时确保函数中的this
关键字指向绑定的对象。
1、什么是bind
bind()
方法创建一个新的函数,在bind()被调用时,这个新函数的this
被指定 bind()
的第一个参数,而其余参数将作为新函数的参数,供调用时使用。
2、bind的语法
语法:
function.bind(thisArg[, arg1[, arg2[, ...]]])
参数:
thisArg:被绑定到函数上的对象,即当调用绑定后的函数时,函数中的
this
关键字会指向该对象。如果thisArg
参数为null
或undefined
,则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
简述代码:
第一次打印
zimo
,可以理解为是打印对象内的一个属性,此时的this
是指向obj对象
。第二次打印
guizimo
,因为当前环境是对象外,因为当前执行的函数是newGetName()
,因此函数内部的this
指向全局对象。通过
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;
}
简述代码:
- 通过
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
最基本的一种使用方式了,也就是创建一个新的函数。
代码:
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
,可以理解为是打印对象内的一个属性,此时的this
是指向obj对象
。 - 第二次打印
guizimo
,因为当前环境是对象外,因为当前执行的函数是newGetName()
,因此函数内部的this
指向全局对象。 - 通过
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
简述代码:
- 创建了一个
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指向
会丢失。
代码:
<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,公众号【归子莫】,小程序【子莫说】
如果你感觉对你有帮助的话,不妨给我点赞鼓励一下,好文记得收藏哟!
幸好我在,感谢你来!
【JavaScript】你真的熟悉bind吗的更多相关文章
- JavaScript 你真的了解this指向吗
JavaScript 你真的了解this指向吗 前言 终于开始写this指向了,相信这对很多JavaScript的学习者来说是一个非常恐怖的环节,个人认为也算是JavaScript中最难理解的一个知识 ...
- javascript中call,apply,bind的用法对比分析
这篇文章主要给大家对比分析了javascript中call,apply,bind三个函数的用法,非常的详细,这里推荐给小伙伴们. 关于call,apply,bind这三个函数的用法,是学习java ...
- JavaScript - call() , apply() and bind()
参考 https://www.codementor.io/niladrisekhardutta/how-to-call-apply-and-bind-in-javascript-8i1jca6jp h ...
- 理解javascript里的ABC--apply bind call
一,三者共同点 js中的apply,call,bind是对于初学者比较难的概念之一,比如说我..参考几篇文章之后,统一来讲, 1.这三个函数都属于Function.prototype下面的方法,如下图 ...
- 你真的熟悉background吗?
一两个月没更新博客了,因为放假刚在深圳找了实习,一直都比较忙碌,不过我觉得再忙,还是需要时间去沉淀一些东西,工作的时候别人看到的只是你有没有实现最终的结果,但自己是否思考,是否去总结,决定着你工作是否 ...
- JavaScript 之 call apply bind
关键字 this 绑定的方法 this的动态切换,固然为JavaScript创造了巨大的灵活性,但也使得编程变得困难和模糊.有时,需要把this固定下来,避免出现意想不到的情况.JavaScript提 ...
- Javascript 中apply call bind
在 javascript 中,call 和 apply 都是为了改变某个函数运行时的上下文(context)而存在的,换句话说,就是为了改变函数体内部 this 的指向. 先来一个例子: functi ...
- JavaScript中call,apply,bind方法的总结。
why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之前,通常会有这些问题. var a = { user:"追梦子", fn:f ...
- JavaScript中call,apply,bind方法的总结
原文链接:http://www.cnblogs.com/pssp/p/5215621.html why?call,apply,bind干什么的?为什么要学这个? 一般用来指定this的环境,在没有学之 ...
- javascript中apply,call,bind区别,bind兼容等问题总结
1 三者的相似之处: (1).都是用来改变函数的this对象的指向的 (2).都是用第一个参数来做this对象的指向 (3).都可以传参数进去 那么,具体到它们有什么区别呢?请看下面的例子: 两个对象 ...
随机推荐
- MySQL(二)字符集、比较规则与规范
1 字符集的相关操作 MySQL8.0之前的版本,默认字符集为latin1,8.0及之后默认为utfmb3.utfmb4,如果以前的版本忘记修改默认的密码,就会出现乱码的问题. 1.1 修改步骤 修改 ...
- Redis(八)redis新功能
redis6新功能 1 ACL Redis ACL是AccessControlList(访问控制表)的缩写,该功能允许根据可以执行的命令和访问的键来限制某些连接. 2 基本命令 acl help &g ...
- elasticsearch升级和索引重建。
1.背景描述 2020年团队决定对elasticsearch升级.es(elasticsearch缩写,下同)当前版本为0.9x,升级到5.x版本.es在本公司承载三个部分的业务,站内查询,订单数 ...
- COIG:开源四类中文指令语料库
CHINESE OPEN INSTRUCTION GENERALIST: A PRELIMINARY RELEASE 论文:https://arxiv.org/pdf/2304.07987v1.pdf ...
- 线上诊断神器-arthas基本应用
Arthas基本应用 一.Arthas作用 什么是Arthas呢? Arthas 是一款阿里推出的线上监控诊断产品,通过全局视角实时查看应用 load.内存.gc.线程的状态信息,并能在不修改应用 ...
- 33-webpack详细配置output
const { resolve } = require('path') const HtmlWebpackPlugin = require('html-webpack-plugin') module. ...
- 一文详解RocketMQ-Spring的源码解析与实战
摘要:这篇文章主要介绍 Spring Boot 项目使用 rocketmq-spring SDK 实现消息收发的操作流程,同时笔者会从开发者的角度解读 SDK 的设计逻辑. 本文分享自华为云社区< ...
- golang调用sdl2,播放pcm音频,报错signal arrived during external code execution。
golang调用sdl2,播放pcm音频,报错signal arrived during external code execution. win10 x64下测试成功,其他操作系统下不保证成功. 采 ...
- 2022-04-16:在一个10^6 * 10^6的网格中, source = [sx, sy]是出发位置,target = [tx, ty]是目标位置, 数组blocked是封锁的方格列表,被禁止的
2022-04-16:在一个10^6 * 10^6的网格中, source = [sx, sy]是出发位置,target = [tx, ty]是目标位置, 数组blocked是封锁的方格列表,被禁止的 ...
- 2022-02-24:k8s安装rabbitmq,yaml如何写?
2022-02-24:k8s安装rabbitmq,yaml如何写? 答案2022-02-24: yaml如下: apiVersion: apps/v1 kind: Deployment metadat ...