javascript基础十七:bind、call、apply 区别?如何实现apply、call、bind?

news/2024/4/19 0:09:54

在这里插入图片描述
一、作用
call、apply、bind作用是改变函数执行时的上下文,简而言之就是改变函数运行时的this指向
那么什么情况下需要改变this的指向呢?
举个粟子:

var name = '小爱同学'
undefined
const obj = {name:'allen ye',say:function(){console.log(this.name)}
}
obj.say()
allen ye // this指向obj对象
undefined
setTimeout(obj.say,0)
小爱同学 // this指向window对象

从上面可以看到,正常情况say方法输出allen ye

但是我们把say放在setTimeout方法中,在定时器中是作为回调函数来执行的,因此回到主栈执行时是在全局执行上下文的环境中执行的,这时候this指向window,所以输出小爱同学

我们实际需要的是this指向obj对象,这时候就需要该改变this指向了

setTimeout(obj.say.bind(obj),0); //allen ye,this指向obj对象

二、区别

下面再来看看apply、call、bind的使用

apply
apply接受两个参数,第一个参数是this的指向,第二个参数是函数接受的参数,以数组的形式传入
改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){console.log(this,args);
}
let obj = {myname:"张三"
}fn.apply(obj,[1,2]); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.apply(null,[1,2]); // this指向window
fn.apply(undefined,[1,2]); // this指向window

call
call方法的第一个参数也是this的指向,后面传入的是一个参数列表

跟apply一样,改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次

function fn(...args){console.log(this,args);
}
let obj = {myname:"张三"
}fn.call(obj,1,2); // this会变成传入的obj,传入的参数必须是一个数组;
fn(1,2) // this指向window

同样的,当第一个参数为null、undefined的时候,默认指向window(在浏览器中)

fn.call(null,[1,2]); // this指向window
fn.call(undefined,[1,2]); // this指向window

bind
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入)
改变this指向后不会立即执行,而是返回一个永久改变this指向的函数

function fn(...args){console.log(this,args);
}
let obj = {myname:"张三"
}const bindFn = fn.bind(obj); // this 也会变成传入的obj ,bind不是立即执行需要执行一次
bindFn(1,2) // this指向obj
fn(1,2) // this指向window

小结
从上面可以看到,apply、call、bind三者的区别在于:

  • 三者都可以改变函数的this对象指向
  • 三者第一个参数都是this要指向的对象,如果如果没有这个参数或参数为undefined或null,则默认指向全局window
  • 三者都可以传参,但是apply是数组,而call是参数列表,且apply和call是一次性传入参数,而bind可以分为多次传入
  • bind是返回绑定this之后的函数,apply、call 则是立即执行

三、实现
实现bind的步骤,我们可以分解成为三部分:

  • 修改this指向
  • 动态传递参数
  • 兼容new关键字
// 方式一:只在bind中传递函数参数
fn.bind(obj,1,2)()// 方式二:在bind中传递函数参数,也在返回函数中传递参数
fn.bind(obj,1)(2)

整体实现代码如下:


Function.prototype.myBind = function(context) {if (typeof this !== 'function') {throw new TypeError('Error')}let _this = thislet args = [...arguments].slice(1)return function F() {// 判断是否被当做构造函数使用if (this instanceof F) {return _this.apply(this, args.concat([...arguments]))}return _this.apply(context, args.concat([...arguments]))}
}

call的实现

Function.prototype.myCall = function(context) {// 判断是否是undefined和nullif (typeof context === 'undefined' || context === null) {context = window}context.fn = thislet args = [...arguments].slice(1)let result = context.fn(...args)delete context.fnreturn result
}

apply的实现

Function.prototype.myApply = function(context) {if (typeof context === 'undefined' || context === null) {context = window}context.fn = thislet args = arguments[1]let resultif (args) {result = context.fn(...args)} else {result = context.fn()}delete context.fnreturn result
}

https://dhexx.cn/news/show-4626201.html

相关文章

全局流控 or 端到端拥塞控制

同事推荐一篇论文 Bolt: Sub-RTT Congestion Control for Ultra-Low Latency,写点想法。 端到端原则使网络在拥塞控制中始终扮演配角,人们认为拥塞控制是端到端的事。几十年来人们设计的拥塞控制机制始终围绕 “主机在什么情况下要增减 cwnd” 打转。但…

2023 华为 Datacom-HCIE 真题题库 07/12--含解析

多项选择题 1.[试题编号:190187] (多选题)如图所示的拓扑采用了VXLAN分布式网关,SW1上的VBDIF10配置了:arp-proxy local enable命令,则以下描述中正确的有哪些项? A、SW1收到PC1发往PC2的报文&…

【计算机组成原理·笔记】总线控制

总线控制 总线上连接多个部件,为了解决: 什么时候由哪个部件发送信息如何给信息传送定时如何防止信息丢失如何避免多个部件同时发送如何规定接受信息的部件 等一些列问题,需要总线控制线进行统一管理,这就是总线控制&#xff0…

angular环境安装 (含nodejs详细安装步骤)

在安装本次环境之前,需要先把本机上的nodejs环境卸载,环境变量手动删除!安装过程种环境才不会产生副作用!实际项目安装的一次记录,踩了太多坑,记录一下,旨在记录!项目需要两个不用版…

网络重置后无法上网,以太网和无线网全部丢失,网络适配器出现“56”错误码

文章目录 一、问题描述电脑系统:电脑问题:解决方案 二、问题过程1. IP问题2.网络重置问题3.电脑无法启动问题 三、解决方案1.卸载2.安全模式检查修复3.软件下载1.CCleaner2.驱动精灵万能网卡版 四、参考链接 一、问题描述 电脑系统: Window…

一次诡异405 METHOD_NOT_ALLOWED “Request method ‘POST‘ not supported“问题排查记录

概述 任何稍微只要有一点经验的开发者都知道HTTP 405,表示方法不支持。如,本来是定义为POST接口,前端使用GET请求,就会报错。 但是我还真遇上一次405 METHOD_NOT_ALLOWED "Request method POST not supported"问题&am…

【考研·数据结构】408真题 (2012年42题) 寻找第一个公共后缀的位置】

代码思路: 代码思路如下: 定义两个指针 p 和 q 分别指向链表 str1 和 str2 的第一个节点(即头结点的下一个节点),并进行循环。对于每个节点 p,都将指针 q 重新指向链表 str2 的第一个节点,然后…

红黑树的 概念性质 和 详解实现(插入旋转等)

文章目录 概念满足的条件性质实现红黑树的定义红黑树节点插入操作情况一情况二情况三Insert()总代码 其余操作左右单旋RotateL 左单旋RotateR 右单旋prevCheck 红黑树性质检测isBalance 红黑树平衡判断InOrder 中序遍历 完整代码 概念 红黑树,是一种二叉搜索树&…

插入排序,选择算法与快速排序(c语言,Java语言)

插入排序 原理:从数组的第二个元素开始,将数组中的每一个元素按照(升序或者降序)规则插入到已排好序的数组中以达到排序的目的。 插入排序并不是将元素取出来,插入到合适位置,之后的元素的位置依次加一,而…

职场恶霸00后,看完这篇你就知道了

在程序员职场上,什么样的人最让人反感呢? 是技术不好的人吗?并不是。技术不好的同事,我们可以帮他。 是技术太强的人吗?也不是。技术很强的同事,可遇不可求,向他学习还来不及呢。 真正让人反感的,是技术平平&#x…