你真的弄懂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…...

2023金三银四应届生求职面试指南
一、应届生优势 划重点,一定要走校招;千万不要等毕业之后再想着找工作,在毕业前就要敲定落实;否则,就真的该焦虑了。要知道应届生的身份是一个很吃香的身份;只有应届生可以走校园招聘。 1、那校园招聘跟社会招聘有多大的差距?? 这么说吧&…...

【数据结构】解决顺序表题的基本方法
🚀write in front🚀 📜所属专栏:> 初阶数据结构 🛰️博客主页:睿睿的博客主页 🛰️代码仓库:🎉VS2022_C语言仓库 🎡您的点赞、关注、收藏、评论࿰…...

HDFS如何解决海量数据存储及解决方案详解
HDFS组件 HDFS组件的基准测试 说明 一般在搭建完集群之后,运维人员需要对集群进行压力测试,对于HDFS来讲,主要是读写测试写入测试 hadoop jar /export/server/hadoop-3.3.0/share/hadoop/mapreduce/hadoop-mapreduce-client-jobclient-3.…...

认识CSS值如何提高写前端代码的效率
🌟所属专栏:前端只因变凤凰之路🐔作者简介:rchjr——五带信管菜只因一枚😮前言:该系列将持续更新前端的相关学习笔记,欢迎和我一样的小白订阅,一起学习共同进步~👉文章简…...

MySQL知识点全面总结3:Mysql高级篇
三.MySQL知识点全面总结3:mysql高级篇 1.mysql语句的执行过程? 2.myesql事务详解? 3.mysql日志详解? 4.mysql的索引功能详解? 5.mysql的存储引擎详解? 6.mysql事务提交后数据与硬盘如何交互存储&…...

Spring注解开发之组件注册(二)
Spring注解开发之组件注册(一) 5.Import 给容器导入一个组件 给容器中注册组件 一、包扫描 组件标注注解(Controller/Service/Repository/Component) [自己写的类] 二、Bean [导入的第三包里面的组件] 三、Import [快速给容器中导入组件] (Import{…...

【web前端开发】CSS最常用的11种选择器
文章目录1.CSS介绍2.CSS的语言规则3.CSS的引入方式4.选择器标签选择器类选择器id选择器通配符选择器复合选择器后代选择器子代选择器并集选择器交集选择器伪类选择器hover伪类选择器active伪类选择器结构伪类选择器结语1.CSS介绍 CSS (Cascading Style Sheets,层叠样…...

微电影广告发展的痛点
微电影广告以不可阻挡之势进入大众生活中,企业利用微电影广告来进行企业形象塑造的例子比比皆是。于是乎,微电影广告在为企业塑造品牌形象方面上取得了可喜的效果,但也不可忽视,在这个发展过程中,微电影广告所面临的问…...

uniapp新手入门
前言: 这篇文章主要写的是uniapp的基础知识,可以让大家快速上手uniapp,同时避掉一些可能踩到的坑。 一. 什么是uniapp uniapp是由dcloud 公司开发的多端融合框架。uniapp的出现让我们的开发更为方便,一次开发,多端运行…...

linux segfault at 问题定位实践
问题:程序崩溃,打印为:app[13016]: segfault at 7fb668d29930 ip 00007fb668d3c23c sp 00007fb668e7de20 error 7 in mydefine.so[7fb668d3400011000]定位步骤:基础分析数据,大概了解反馈信息(根据chatGPT&…...