关于JS中this对象指向问题总结
一、前言
关于JS中this对象指向问题,相信做过项目的小伙伴多多少少都会遇到过,明明感觉代码写的没问题,可是运行的时候,就会报错,比如报错 xxx is not a function。
我最近也遇到了,百度学习了不少前辈对于this对象指向问题的解析,于是总结了这篇文章。
二、多种情况下使用this,指向有所不同
先简略概括下,this在英文中的意思是,“这,这个”的意思,在编程中我们通常把this成为当前对象。在这篇文章中,我们从始至终都要记得一句话:this永远指向,调用它的对象,默认指向window/全局对象。
如果有多层嵌套对象调用的话,this指向最后一次调用这个方法的对象。
1)全局作用域中的this
在全局作用域中,this指向 window/全局对象。
console.log(this) // window对象console.log(this === window) //true

2)函数调用中的this
当一个函数不是一个对象的属性时,直接作为函数来调用;
函数不是箭头函数时,this指向window/全局对象;
函数是箭头函数时,绑定的是父作用域的this指向。
function func(){console.log(this) ; //this指向window对象
}
func();
注意:定时器内部的this永远指向window,比如setTimeout,setInterval
setTimeout(function(){console.log(this); //window对象},1000)
3)对象中的this
如果一个函数作为一个对象的方法来调用时,this 指向这个对象;(比如vue中的methods对象里面定义的函数方法)
箭头函数除外,因为它会捕获其所在上下文的this,所以可能会指向window/全局对象。
let obj = {func: function () {console.log(this)}}obj.func()
在这段代码中,我们看到了 obj.func(),this 处在 func 函数的内部,那到底是谁调用的 func() 哪?显而易见是 obj,因为 this 永远指向,调用它的对象,所以最后的打印结果应该是 obj。
4)使用 new 实例化对象,构造函数中的this
构造函数中的this指向实例出来的对象。
function Person () {console.log(this)this.name = '铁锤妹妹'
}
var obj = new Person() // 得到一个实例化对象,继承了Person函数的属性
console.log(obj)
打印结果:就是Person

5)apply 、call 和 bind 调用中的this
apply和call 改变的是函数运行时的this指向,bind返回一个this绑定了传入对象的新函数。
这个函数的this指向使用new时会被改变。
注意:箭头函数中的this不能通过apply 、call 和 bind 改变,因为箭头函数中的this指向在定义时已经确认了,之后不会被改变。
const obj = { name: '铁锤妹妹', age: 18 }
function Person () {console.log(this.name)
}
Person.apply(obj) //铁锤妹妹
Person.call(obj) //铁锤妹妹
Person.bind(obj)() //铁锤妹妹
6)事件中的this
在事件处理函数中,this指向触发事件的目标对象<div></div>。
document.querySelector('div').onclick = function () {console.log(this) //<div></div>
}
总结:
1. 全局作用域中的this指向window
2. 普通函数this指向window,箭头函数指向它的上下文this
3. 对象中方法的this指向该方法所属的对象
4. 构造函数中的this指向实例出来的对象
5. 事件当中的this指向当前绑定的元素
6. 定时器中的this指向window
7. apply 、call 和 bind 调用中的this指向它想要指向的this
三、改变this指向的方法
- 使用 ES6 的箭头函数
- 在函数内部使用 _this = this
- new 实例化一个对象
- 使用 apply、call、bind
1)箭头函数不绑定this,会捕获其所在上下文的this,作为自己的this
- 这句话需要注意的是,箭头函数的外层如果有普通函数,那么箭头函数的this就是这个外层普通函数的this(它会继承自己作用域上一层的this);箭头函数的外层如果没有普通函数,那么箭头函数的this就是window/全局对象。
- 箭头函数中的this指向在定义时已经确认了,之后不会被改变。
下面这个例子是箭头函数外层有普通函数。
var name = 'windowsName'var a = {name: '铁锤妹妹',func1: function () {console.log(this.name)},func2: function () {setTimeout(() => {this.func1()}, 100)}}a.func2() //铁锤妹妹
如果不使用箭头函数,运行会报错,原因是使用普通函数时,调用的setTimeout的对象是Window,而Window中没有定义func1函数。
var name = 'windowsName'var a = {name: '铁锤妹妹',func1: function () {console.log(this.name)},func2: function () {setTimeout(function () {this.func1()}, 100)}}a.func2()
报错信息

2)如果不想使用箭头函数,也可以在函数内部使用var _this = this
var name = 'windowsName'var a = {name: '铁锤妹妹',func1: function () {console.log(this.name)},func2: function () {var _this = thissetTimeout(function () {_this.func1()}, 100)}}a.func2() //铁锤妹妹
在 func2 中,首先设置 var _this = this,这里的this是调用 func2 的对象a,因为a是最后一次调用这个方法的对象;
为了防止在 func2 中的 setTimeout 被 window 调用而导致 setTimeout 中的 this 指向变为 window对象。我们将this(指向变量a)赋值给一个变量 _this,这样在 func2 中我们使用 _this 就是指向对象 a 了。
3)如果一个函数用 new 调用时,函数执行前会新创建一个对象,this 指向这个新创建的对象
new操作符的执行过程:
- 首先创建了一个空的对象(创建一个新的存储空间)
- 设置原型,将对象的原型设置为函数的 prototype 对象
- 让函数的this指向这个新空对象,执行构造函数的代码(为这个新对象添加属性和方法)
- 返回新对象(所以构造函数不需要return)
因此,使用new 实例化对象,构造函数中的this指向实例化对象。
注意:上面说的箭头函数除外,因为箭头函数是匿名函数,不能作为构造函数,所以不能使用new命令,否则抛出错误。
//箭头函数使用new实例化报错代码
let func1 = () => {}
let func2 = new func1()
console.log(func2) // func1 is not a constructor
4)使用apply、call和bind指定 调用函数 的this指向
var year = 2023function getDate (month, day) {return this.year + '-' + month + '-' + day}let obj = { year: 1998 }getDate.call(null, 3, 8) // 2023-3-8getDate.call(obj, 3, 8) // 1998-3-8getDate.apply(obj, [6, 8]) // 1998-6-8getDate.bind(obj)(3, 8) // 1998-3-8
使用 apply() 方法
apply接受两个参数,第一个是this的指向,第二个是函数接受的参数,以数组的形式传入,且当第一个参数为null、undefined的时候,默认指向window(在浏览器中);使用apply方法改变this指向后原函数会立即执行,且此方法只是临时改变this指向一次。
- 语法规则 :
函数名称.apply(obj,[arg1,arg2…,argN])- 参数说明:
obj :this要指向的对象
[arg1,arg2…argN] : 参数列表,要求格式为数组
使用 call() 方法
call 方法的第一个参数也是this的指向,后面传入的是一个参数列表。当第一个参数为null、undefined的时候,表示指向window。和apply一样,call也只是临时改变一次this指向,并立即执行。
- 语法规则 :
函数名称.call(obj,arg1,arg2…argN)- 参数说明:
obj :this要指向的对象
arg1,arg2…argN : 参数列表,参数与参数之间使用一个逗号隔开
注意:call和apply的作用一致,区别仅仅在函数实参参数传递的方式上;
使用 bind() 方法
bind方法和call很相似,第一参数也是this的指向,后面传入的也是一个参数列表(但是这个参数列表可以分多次传入,call则必须一次性传入所有参数),但是它改变this指向后不会立即执行,而是返回一个永久改变this指向的函数,调用新函数的时候才会执行目标函数。
三、关于setTimeout() 定时器的“this”指向问题
由setTimeout()调用的代码运行在与所在函数完全分离的执行环境上。这会导致,这些代码中包含的 this 关键字会指向 window (或全局) 对象,这和所期望的this的值是不一样的。
var name = 'windowsName'var a = {name: '铁锤妹妹',func1: function () {setTimeout(function () {console.log(this.name, 'name')}, 100)}}a.func1()//因为setTimeout,所以this指向window//打印结果:windowsName
四、总结本文箭头函数需要注意的地方
1. 函数是箭头函数的话,指向它的上下文对象的yhis
2. 箭头函数中的this不能通过apply 、call 和 bind 改变,因为箭头函数中的this指向在定义时已经确认了,之后不会被改变
3. 箭头函数使用new实例化对象时会报错
相关文章:
关于JS中this对象指向问题总结
一、前言 关于JS中this对象指向问题,相信做过项目的小伙伴多多少少都会遇到过,明明感觉代码写的没问题,可是运行的时候,就会报错,比如报错 xxx is not a function。 我最近也遇到了,百度学习了不少前辈对于…...
Codeforces Round 855 (Div. 3) A-E2
比赛链接:Dashboard - Codeforces Round 855 (Div. 3) - Codeforces A:模拟 题意:给定一个字符串,问这个字符串是不是猫叫。定义是猫叫得字符串: 1:必须由大写或小写得M(m),E&…...
Spark Yarn 运行环境搭建
文章目录Spark Yarn 运行环境搭建1、解压缩文件2、修改配置环境文件3、配置历史服务器Spark Yarn 运行环境搭建 1、解压缩文件 将spark3.2.3的压缩包上传到 linux /opt/software 目录下 输入命令: tar -zxvf spark-3.2.3-bin-hadoop3.2-scala2.13.tgz -C /opt/ 解…...
SpringMVC 页面跳转指南:转发和重定向的实现与比较
SpringMVC 是一款非常流行的 Java Web 框架,它提供了丰富的特性和功能,使得开发者可以轻松地开发 Web 应用程序。其中,转发和重定向是 SpringMVC 中非常常见的两个操作,它们可以用于控制请求的流转和页面的跳转。本文将深入探讨 S…...
ModStartCMS v5.9.0 后台浅色模式,系统样式升级
ModStart 是一个基于 Laravel 模块化极速开发框架。模块市场拥有丰富的功能应用,支持后台一键快速安装,让开发者能快的实现业务功能开发。 系统完全开源,基于 Apache 2.0 开源协议,免费且不限制商业使用。 功能特性 丰富的模块市…...
2020蓝桥杯真题反倍数 C语言/C++
题目描述 给定三个整数 a,b,c,如果一个整数既不是 a 的整数倍也不是 b 的整数倍还不是 c 的整数倍,则这个数称为反倍数。 请问在 1 至 n 中有多少个反倍数。 输入描述 输入的第一行包含一个整数 n。 第二行包含三个整数a,b,c,相邻两个数之…...
PTA:L1-025 正整数A+B、L1-026 I Love GPLT、L1-027 出租(C++)
目录 L1-025 正整数AB 问题描述: 实现代码: L1-026 I Love GPLT 问题描述: 实现代码: L1-027 出租 问题描述: 实现代码: 原理思路: 出租那道题有点意思哈 L1-025 正整数AB 问题描述…...
状态机的Go语言实现版本
一、状态机 1. 定义 有限状态机(Finite-state machine, FSM),简称状态机,是表示有限个状态以及在这些状态之间的转移和动作等行为的数学模型。 2. 组成要素 现态(src state):事务当前所处的状…...
第2章 线程安全与共享资源竞争
第2章 线程安全与共享资源竞争 2.1 synchronized同步介绍 synchronized要解决的是共享资源冲突的问题。当共享资源被任务使用时,要对资源提前加锁。所有任务都采用抢占模式,即某个任务会抢先对共享资源加上第一把锁。如果这是一个排他锁,…...
77. writerows写入多行
文章目录1. 目标任务2. 准备工作3. writerow单行写入4. writerows多行写入5. a以追加的模式写入值6. 总结1. 目标任务 新建【各班级成绩】文件夹; 在该文件夹下新建一个【1班成绩单.csv】文件; 在该文件中写入下面的内容: 成绩 姓名 刘一…...
STM32MP157-Linux输入设备应用编程-多点触摸屏编程
文章目录前言多点触摸屏tslib库简介tslib库移植tslib库函数使用打开触摸屏设备配置触摸屏设备打开并配置触摸屏设备读取触摸屏设备多点触摸屏程序编写触点数据结构体定义事件定义计算触点数量判断单击、双击判断长按、移动判断放大、缩小外部调用代码流程图(草图&am…...
mybatis-plus的一般实现过程(超详细)
MyBatis-Plus 是 MyBatis 的增强工具,在 MyBatis 的基础上提供了许多实用的功能,如分页查询、条件构造器、自动填充等。下面是 MyBatis-Plus 的完整代码实现流程: ①、引入 MyBatis-Plus 依赖 在 Maven 中,可以通过以下方式引入 …...
Spark(5):RDD概述
目录 0. 相关文章链接 1. 什么是RDD 2. RDD核心属性 3. 执行原理 0. 相关文章链接 Spark文章汇总 1. 什么是RDD RDD(Resilient Distributed Dataset)叫做弹性分布式数据集,是 Spark 中最基本的数据处理模型。代码中是一个抽象类&#x…...
面向对象 - 继承
Hello , 各位同学朋友大家好啊, 今天给大家分享的技术呢, 是面向对象三大特征之一的继承,我们今天主要按照以下几个点, 展开继承的讲解。目录 :* 继承的介绍* 继承的好处和弊端* 继承中成员访问特点 - 成员变量* 继承中成员访问特点 - 成员方法* 方法重写* 继承中成…...
计算机网络的166个概念你知道几个 第十二部分
计算机网络安全安全通信的四大要素:机密性、保温完整性、端点鉴别和运行安全性。机密性:报文需要在一定程度上进行加密,用来防止窃听者截取报文。报文完整性:在报文传输过程中,需要确保报文的内容不会发生改变。端点鉴…...
【RabbitMQ】RabbitMQ各版本的兼容性与技术支持时限
今天在研究RabbitMQ的监控时,发现这个消息队列软件的版本真的很令人崩溃,版本众多,且组件之间还存在版本的兼容性,此外各个组件还对操作系统存在兼容性关系。为了帮大家节省一些查阅官方文档的时间,我把官方文档里面涉…...
【Git】P5 Git 远程仓库(3)pull 发生冲突
pull 发生冲突冲突在什么场景下发生?为什么要先 pull 再 push构建一个冲突场景初始开始操作:程序员2:程序员1:程序员2:发生冲突:查看冲突:解决冲突:冲突在什么场景下发生?…...
关于世界坐标系,相机坐标系,图像坐标系,像素坐标系的一些理解
关于世界坐标系,相机坐标系,图像坐标系,像素坐标系的一些理解前言一、各坐标系的含义二、坐标系转换1.世界坐标系与相机坐标系(旋转与平移)2.相机坐标系与图像坐标系(透视)3.图像坐标系与像素坐…...
企业防护ddos的注意事项,你知道吗?
DDoS,分布式拒绝服务攻击,是指处于不同位置的多个攻击者同时向一个或数个目标发动攻击,或者一个攻击者控制了位于不同位置的多台机器并利用这些机器对受害者同时实施攻击。在当下,DDoS 攻击是非常常见的一种攻击方式,大…...
RocketMQ如何测试
RocketMQ如何测试MQ简介RocketMQRocketMQ测试点MQ简介 MQ:Message Queue,即消息队列,是一种应用程序之间的消息通信,简单理解就是A服务不断的往队列里发布信息,另一服务B从队列中读取消息并执行处理,消息发…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...
Web 架构之 CDN 加速原理与落地实践
文章目录 一、思维导图二、正文内容(一)CDN 基础概念1. 定义2. 组成部分 (二)CDN 加速原理1. 请求路由2. 内容缓存3. 内容更新 (三)CDN 落地实践1. 选择 CDN 服务商2. 配置 CDN3. 集成到 Web 架构 …...
CRMEB 中 PHP 短信扩展开发:涵盖一号通、阿里云、腾讯云、创蓝
目前已有一号通短信、阿里云短信、腾讯云短信扩展 扩展入口文件 文件目录 crmeb\services\sms\Sms.php 默认驱动类型为:一号通 namespace crmeb\services\sms;use crmeb\basic\BaseManager; use crmeb\services\AccessTokenServeService; use crmeb\services\sms\…...
适应性Java用于现代 API:REST、GraphQL 和事件驱动
在快速发展的软件开发领域,REST、GraphQL 和事件驱动架构等新的 API 标准对于构建可扩展、高效的系统至关重要。Java 在现代 API 方面以其在企业应用中的稳定性而闻名,不断适应这些现代范式的需求。随着不断发展的生态系统,Java 在现代 API 方…...
LCTF液晶可调谐滤波器在多光谱相机捕捉无人机目标检测中的作用
中达瑞和自2005年成立以来,一直在光谱成像领域深度钻研和发展,始终致力于研发高性能、高可靠性的光谱成像相机,为科研院校提供更优的产品和服务。在《低空背景下无人机目标的光谱特征研究及目标检测应用》这篇论文中提到中达瑞和 LCTF 作为多…...
Linux中《基础IO》详细介绍
目录 理解"文件"狭义理解广义理解文件操作的归类认知系统角度文件类别 回顾C文件接口打开文件写文件读文件稍作修改,实现简单cat命令 输出信息到显示器,你有哪些方法stdin & stdout & stderr打开文件的方式 系统⽂件I/O⼀种传递标志位…...
LLaMA-Factory 微调 Qwen2-VL 进行人脸情感识别(二)
在上一篇文章中,我们详细介绍了如何使用LLaMA-Factory框架对Qwen2-VL大模型进行微调,以实现人脸情感识别的功能。本篇文章将聚焦于微调完成后,如何调用这个模型进行人脸情感识别的具体代码实现,包括详细的步骤和注释。 模型调用步骤 环境准备:确保安装了必要的Python库。…...
【UE5 C++】通过文件对话框获取选择文件的路径
目录 效果 步骤 源码 效果 步骤 1. 在“xxx.Build.cs”中添加需要使用的模块 ,这里主要使用“DesktopPlatform”模块 2. 添加后闭UE编辑器,右键点击 .uproject 文件,选择 "Generate Visual Studio project files",重…...
macOS 终端智能代理检测
🧠 终端智能代理检测:自动判断是否需要设置代理访问 GitHub 在开发中,使用 GitHub 是非常常见的需求。但有时候我们会发现某些命令失败、插件无法更新,例如: fatal: unable to access https://github.com/ohmyzsh/oh…...
DAY 26 函数专题1
函数定义与参数知识点回顾:1. 函数的定义2. 变量作用域:局部变量和全局变量3. 函数的参数类型:位置参数、默认参数、不定参数4. 传递参数的手段:关键词参数5 题目1:计算圆的面积 任务: 编写一…...
