你真的弄懂this指向了吗
前言
在说 this 指向之前,请观察以下代码,并说出它们的输出结果:
第 1 组:标准函数
window.color = "red";
let o = {color: "blue",
};
function sayColor() {console.log(this.color);
}sayColor(); // 输出值是什么?o.sayColor = sayColor;
o.sayColor(); // 输出值是什么?
第 2 组:箭头函数
window.color = "red";
let o = {color: "blue",
};
let sayColor = () => console.log(this.color);sayColor(); // 输出值是什么?o.sayColor = sayColor;
o.sayColor(); // 输出值是什么?
一、标准函数和箭头函数的 this 指向
先公布一下以上函数的输出结果,不知道屏幕前的你答对了吗?
第 1 组输出结果如下
sayColor(); // 'red'
o.sayColor(); // 'blue'
第 2 组输出结果如下
sayColor(); // 'red'
o.sayColor(); // 'red'
为什么会呈现出这样的输出结果呢?
标准函数中,this 指向的是把函数当成方法调用的上下文对象,在网页的全局上下文中调用函数时,this 指向 window,因此 this 指向是会发生改变的
箭头函数中,this 指向的是定义箭头函数的上下文对象,箭头函数在哪个对象的上下文中定义的,this 就指向谁,,箭头函数中,this 的指向是固定的
二、改变 this 指向
我们知道,函数其实是一个对象,因此它有属性和方法。每个函数都有两个属性:length 和 prototype。其中 length 属性保存函数定义的命名参数的个数,prototype 属性保存引用类型所有实例和方法。call、apply、bind ,就是保存在 prototype 中的方法。
前面已经提到,标准函数和箭头函数的默认 this 指向,但是在某些时候,我们需要改变 this 的 默认指向,这时候我们就需要用到 call、apply、bind 方法,这 3 个方法都可以用来改变 this 指向,接下来我们来详细介绍这 3 个方法。
1. call
call() 方法会以指定的 this 值来调用函数,即会设置调用函数时函数体内 this 对象的值。 call() 方法接收两个参数,第 1 个参数是函数内的 this 值,第 2 个参数是调用该函数需要传入的值。第 1 个参数是必填项,第 2 个参数可以不填。
call(this, num);
以前言中的代码举例,观察 this 的变化
window.color = "red";
let o = {color: "blue",
};function sayColor() {console.log(this.color);
}sayColor(); // 'red'sayColor.call(o); // 'blue'
sayColor 是一个标准函数,它的 this 指向是调用时的上下文对象,我们是在全局调用的,因此它的上下文对象应该是 window,所以 sayColor() 输出 'red' 是毫无疑问的。但是 sayColor.call(o) 为什么会输出 'blue' 呢?虽然它也是在全局上下文中调用的,但是我们利用 call() 方法,给它指定了一个新的 this 值,也就是对象 o,所以这里的 this.color 指的是对象 o 中的 color。
call() 方法传值需要将参数一个一个列出来,用 ',' 分开,从第 2 个参数开始,看下面示例:
function sum(num1, num2) {return num1 + num2;
}
num.call(this, 10, 20); // 30
2. apply
apply() 方法和 call() 作用一样,第一个参数也是指定 this 值,但是参数需要是 Array 实例或者 arguments 对象,看下面示例:
function sum(num1, num2) {return num1 + num2;
}function callSum1(num1, num2) { return sum.apply(this, arguments);
}function callSum2(num1, num2) {return sum.apply(this, [num1, num2]);
}console.log(callSum1(10, 20)); // 30
console.log(callSum2(10, 20)); // 30
从示例中可以看出,无论是传入类数组对象还是数组,可以进行正常的传值。call() 和 apply() 真正强大的地方在于,它们可以控制函数调用上下文,可以将任意对象设置为任意函数的作用域。
3. bind
与 call() 和 apply() 不同,bind() 方法会新创建一个函数实例,这个新函数的 this 值,会绑定到传给 bind() 的对象。下面来看示例:
window.color = "red";
let o = {color: "blue",
};function sayColor() {console.log(this.color);
}
let objectSayColor = sayColor.bind(o);objectSayColor(); // 'blue'
在这里,我们在 sayColor() 上调用了 bind() 方法,并传入了一个对象 o ,创建了一个新的函数 objectSayColor(),指定其作用域为对象 o。所以,我们在任意地方调用该函数,输出的都是字符串 'blue'。
4. 三者之间的区别
通过以上的分析,我们已经知道,call() 、apply() 、bind() 都可以用来修改 this 指向。它们的区别如下:
call()、apply()是直接修改原函数的this 值,不会创建新的函数call()传值需要将值一个一个列出来,用','隔开apply()只能传入数组格式或者类数组格式的值bind()会返回一个修改过this 值的新函数
三、总结
call() 、apply() 、bind() 是为了灵活改变函数 this 指向而发明的,他们的主要用途也是用来改变 this 指向。当然,由于这些方法本身的特性,也可以用来做些其它的事情,比如计算数组最大值、最小值等。
不过,这个用途并不广泛,因为解构赋值可以更轻松达到这个目的。
const arr = [1, 2, 3, 4, 5];Math.max.apply(this, arr);
Math.min.apply(this, arr);Math.max(...arr);
Math.min(...arr);
相关文章:
你真的弄懂this指向了吗
前言 在说 this 指向之前,请观察以下代码,并说出它们的输出结果: 第 1 组:标准函数 window.color "red"; let o {color: "blue", }; function sayColor() {console.log(this.color); }sayColor(); // 输…...
阿里云服务器使用教程:使用xshell、xFtp工具连接阿里云服务器(Centos7)并修改Centos7的yum源为阿里镜像源
目录 1、下载并安装xshell、xFtp 2、远程连接阿里云服务器 3、 修改Centos7的yum源为阿里镜像源 1、下载并安装xshell、xFtp XShell可以在Windows界面下来访问远端不同系统下的服务器,从而比较好的达到远程控制终端的目的。它支持 RLOGIN、SFTP、SERIAL、TELNET、…...
一文快速入门 HTML 网页基础
专栏简介: 前端从入门到进阶 题目来源: leetcode,牛客,剑指offer. 创作目标: 记录学习JavaEE学习历程 希望在提升自己的同时,帮助他人,,与大家一起共同进步,互相成长. 学历代表过去,能力代表现在,学习能力代表未来! 目录 1.HTML 结构 1.1. 认识 HTML 标签 1.2 HTML 文件结构…...
DEJA_VU3D - Cesium功能集 之 100-任意多边形(标绘)
前言 编写这个专栏主要目的是对工作之中基于Cesium实现过的功能进行整合,有自己琢磨实现的,也有参考其他大神后整理实现的,初步算了算现在有差不多实现小140个左右的功能,后续也会不断的追加,所以暂时打算一周2-3更的样子来更新本专栏(每篇博文都会奉上完整demo的源代码,…...
Cadence OrCAD Capture全局修改原理图的非本地库符号的方法图文教程Repalce Catch功能
⏪《上一篇》 🏡《总目录》 ⏩《下一篇》 目录 1,概述2,修改方法2.1,新建本地库2.2,待修改搬入本地库2.3,修改原理图符号2.4,全局更新原理图符号3,总结B站关注“硬小二”浏览更多演示视频 1,概述 在完成原理图设计...
npm包版本号详解
npm包在发布时,需要按照包版本语义化中的约定去更新设置,例如我们常见的1.0.0,1.0.1,0.0.1等这样的版本号,那么这些数字分别代表什么意思呢?下面我们将详细介绍。 npm版本号的组成 一个完整的版本号&…...
ubuntu 系统安装docker——使用docker打包python项目,整个流程介绍
目录 1 安装docker和配置镜像源 2 下载基础镜像 3 通过镜像创建容器 4 制作项目所需的容器 5 容器制作好后打包为镜像 6 镜像备份为.tar文件 7 从其他服务器上恢复镜像 8 docker的其他常用指令 首先科普一下镜像、容器和实例; 镜像:相当于安装包&…...
MySQL事务篇
MySQL事务篇 一、一条Insert语句 为了故事的顺利发展,我们需要创建一个表: CREATE TABLE t (id INT PRIMARY KEY,c VARCHAR(100) ) EngineInnoDB CHARSETutf8;然后向这个表里插入一条数据: INSERT INTO t VALUES(1, 刘备); 现在表里的数据就…...
【Redis】搭建分片集群
目录 集群结构 准备实例和配置 启动 创建集群 测试 集群结构 分片集群需要的节点数量较多,这里我们搭建一个最小的分片集群,包含3个master节点,每个 master包含一个slave节点,结构如下: 这里我们会在同一台虚…...
RoCEv2网络部署实践
延续上篇RoCE网络的介绍,我们知道承载ROCEv2流量必须有一张无损网络。 本章主要介绍在以太网环境部署无损网络的关键点。 首先是QoS,包含流分类和队列调度两部分。 流分类:在网络接入设备(TOR)配置if-match类的语句&am…...
【HashMap】| 深度剥析Java SE 源码合集Ⅱ | 你会吗?
目录一. 🦁 HashMap介绍1.1 特点1.2 底层实现二. 🦁 结构以及对应方法分析2.1 结构组成2.1.1 成员变量2.1.2 存储元素的节点类型2.1.2.1 链表Node类2.1.2.2 树节点类2.1.2.3 继承关系2.2 方法实现2.2.1 HashMap的数组初始化2.2.2 计算hash值2.2.3 添加元…...
剑指 Offer 39. 数组中出现次数超过一半的数字
剑指 Offer 39. 数组中出现次数超过一半的数字 难度:easy\color{Green}{easy}easy 题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: …...
使用python控制摄像头
前言 当今,随着计算机技术的发展,摄像头已经成为了人们生活中不可或缺的一部分。而Python作为一种流行的编程语言,也可以轻松地控制和操作摄像头。无论你是想用Python写一个简单的摄像头应用程序,还是想在机器学习和计算机视觉项…...
Linux文件系统
目录 1、常见的linux文件系统 2、文件系统的组成 inode的内容: 可以用stat命令,查看某个文件的inode信息 inode的大小 inode号码 使用 ls -i来查看文件的inode号码 使用 df -i命令,查看每个硬盘分区的inode总数和已经使用的数量ÿ…...
扬帆优配|引活水 增活力 促转型 创业板助力实体经济高质量发展
立异就是生产力,企业赖之以强,国家赖之以盛。全面注册制变革持续开释立异生机。日前,创业板公司已开端连续公布2022年度年度报告和2023年第一季度成绩预告,从频频传来的“喜报”中可窥见立异驱动开展战略下新兴工业的强劲开展态势…...
【c++】:STL模板中string的使用
文章目录 STL简介一.认识string二.string中基本功能的使用总结STL简介 STL(standard template libaray-标准模板库):是C标准库的重要组成部分,不仅是一个可复用的组件库,而且是一个包罗数据结构与算法的软件框架。STL的版本 原始版本 Alexand…...
华为OD机试用Python实现 -【连续字母长度 or 求第 K 长的字符串长度】 | 2023.Q1 A卷
华为OD机试题 本篇题目:连续字母长度 or 求第 K 长的字符串长度题目输入描述输出描述示例一输入输出说明示例二输入输出说明示例三输入输出说明Code代码编写逻辑最近更新的博客 华为od 2023 | 什么是华为od,od...
前端处理并发的最佳实践
什么是并发? 因为js是单线程的,所以前端的并发指的是在极短时间内发送多个数据请求,比如说循环中发送ajax。 举一个简单的例子: 下面一段代码是常规的mount阶段执行的请求: useEffect(async () > {console.time…...
【SOP 】配电网故障重构方法研究【IEEE33节点】(Matlab代码实现)
💥💥💞💞欢迎来到本博客❤️❤️💥💥 🏆博主优势:🌞🌞🌞博客内容尽量做到思维缜密,逻辑清晰,为了方便读者。 ⛳️座右铭&a…...
[MySQL索引]4.索引的底层原理(三)
索引的底层原理(三)哈希索引InnoDB自适应哈希索引哈希索引 memory存储引擎支持的是哈希索引,memory是支持内存的存储引擎。 哈希表中的元素没有任何顺序可言,只能进行等值比较,包括范围搜索、前缀搜索like、order by…...
Frozen-Flask :将 Flask 应用“冻结”为静态文件
Frozen-Flask 是一个用于将 Flask 应用“冻结”为静态文件的 Python 扩展。它的核心用途是:将一个 Flask Web 应用生成成纯静态 HTML 文件,从而可以部署到静态网站托管服务上,如 GitHub Pages、Netlify 或任何支持静态文件的网站服务器。 &am…...
实现弹窗随键盘上移居中
实现弹窗随键盘上移的核心思路 在Android中,可以通过监听键盘的显示和隐藏事件,动态调整弹窗的位置。关键点在于获取键盘高度,并计算剩余屏幕空间以重新定位弹窗。 // 在Activity或Fragment中设置键盘监听 val rootView findViewById<V…...
Angular微前端架构:Module Federation + ngx-build-plus (Webpack)
以下是一个完整的 Angular 微前端示例,其中使用的是 Module Federation 和 npx-build-plus 实现了主应用(Shell)与子应用(Remote)的集成。 🛠️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
R语言速释制剂QBD解决方案之三
本文是《Quality by Design for ANDAs: An Example for Immediate-Release Dosage Forms》第一个处方的R语言解决方案。 第一个处方研究评估原料药粒径分布、MCC/Lactose比例、崩解剂用量对制剂CQAs的影响。 第二处方研究用于理解颗粒外加硬脂酸镁和滑石粉对片剂质量和可生产…...
C++实现分布式网络通信框架RPC(2)——rpc发布端
有了上篇文章的项目的基本知识的了解,现在我们就开始构建项目。 目录 一、构建工程目录 二、本地服务发布成RPC服务 2.1理解RPC发布 2.2实现 三、Mprpc框架的基础类设计 3.1框架的初始化类 MprpcApplication 代码实现 3.2读取配置文件类 MprpcConfig 代码实现…...
内窥镜检查中基于提示的息肉分割|文献速递-深度学习医疗AI最新文献
Title 题目 Prompt-based polyp segmentation during endoscopy 内窥镜检查中基于提示的息肉分割 01 文献速递介绍 以下是对这段英文内容的中文翻译: ### 胃肠道癌症的发病率呈上升趋势,且有年轻化倾向(Bray等人,2018&#x…...
leetcode_69.x的平方根
题目如下 : 看到题 ,我们最原始的想法就是暴力解决: for(long long i 0;i<INT_MAX;i){if(i*ix){return i;}else if((i*i>x)&&((i-1)*(i-1)<x)){return i-1;}}我们直接开始遍历,我们是整数的平方根,所以我们分两…...
stm32进入Infinite_Loop原因(因为有系统中断函数未自定义实现)
这是系统中断服务程序的默认处理汇编函数,如果我们没有定义实现某个中断函数,那么当stm32产生了该中断时,就会默认跑这里来了,所以我们打开了什么中断,一定要记得实现对应的系统中断函数,否则会进来一直循环…...
算法刷题-回溯
今天给大家分享的还是一道关于dfs回溯的问题,对于这类问题大家还是要多刷和总结,总体难度还是偏大。 对于回溯问题有几个关键点: 1.首先对于这类回溯可以节点可以随机选择的问题,要做mian函数中循环调用dfs(i&#x…...
