JS中this的值详细讲解以及面试指向练习
this
的值取决于它出现的上下文:函数、类或全局。
在函数内部,this
的值取决于函数如何被调用,this
是语言在函数体被执行时为你创建的绑定
对于典型的函数,this
的值是函数被访问的对象。换句话说,如果函数调用的形式是 obj.f()
,那么 this
就指向 obj,例如
function getThis() {return this;
}const obj1 = { name: "obj1" };
const obj2 = { name: "obj2" };obj1.getThis = getThis;
obj2.getThis = getThis;console.log(obj1.getThis()); // { name: 'obj1', getThis: [Function: getThis] }
console.log(obj2.getThis()); // { name: 'obj2', getThis: [Function: getThis] }
注意,虽然函数是相同的,但是根据其调用的方式,
this
的值是不同的。这与函数参数的工作方式类似。
this到底指向谁
调用函数会创建新的属于函数自身的执行上下文,执行上下文的调用创建阶段会决定this的指向,结论:this的指向,是在调用函数时根据执行上下文所动态确定的,或者说this关键字指向函数(方法)运行时的所有者
1.规则:
- 在函数体中,简单调用该函数时(非显式/隐式绑定下),严格模式下this绑定到undefined,否则绑定到全局对象window/global
- 一般构造函数new调用,绑定到新创建的对象上
- 一般由call/bind/apply方法显式调用,绑定到指定参数的对象上
- 一般由上下文对象调用,绑定在该对象上
- 箭头函数中,根据外层上下文绑定的this决定this的指向
2.实例分析练习
(1)全局环境下的this
function f1(){console.log(this);
}function f2() {'use strict'console.log(this);
}f1() //Window对象
f2() //undefined
const foo = {bar: 10,fn: function () {console.log(this); //Windowconsole.log(this.bar); //undefined}
}var fn1=foo.fn
fn1()
上题中this指向的是window,虽然fn函数在foo对象中作为方法被引用,但是在赋值给fn1后,fn1的执行仍然是在window的全局环境中
const foo = {bar: 10,fn: function () {console.log(this); //{bar:10,fn:f}console.log(this.bar); //10}
}foo.fn()
上题中this指向的是最后调用他的对象,在foo.fn()语句中this指向foo对象
注意:在执行函数时,如果函数中的this是被上一级的对象所调用,那么this指向的就是上一级的对象;否则指向全局环境
(2)上下文对象调用中的this
const student={name:'hist',fn:function(){return this}
}console.log(student.fn()===student); //true
const person = {name: 'hist',brother: {name: 'comp',fn: function () {return this.name}}
}console.log(person.brother.fn()); //comp
上题在这种嵌套关系中,this指向最后调用它的对象
const o1 = {text: 'o1',fn: function () {return this.text}
}const o2 = {text: 'o2',fn: function () {return o1.fn()}
}const o3 = {text: 'o3',fn: function () {var fn= o1.fnreturn fn()}
}console.log(o1.fn()); //o1
console.log(o2.fn()); //o1
console.log(o3.fn()); //undefined
第二个相当于最后调用时还是用o1调用的fn()
第三个将o1.fn()赋值给fn后,直接调用fn(),没有用对象点调用,所以这里this指向window
如果想让第二个输出o2怎么做?
const o2 = {text: 'o2',fn: o1.fn() }
此时我们将赋值操作提前,相当于先把o1.fn()变为this.text,此时我们用o2调用fn()指向的就是o2对象
(3)bind/call/apply改变this指向
补充:bind/call/apply使用方法
const target={}fn.call(target, 'arg1', 'arg2') fn.apply(target,['arg1','arg2']) fn.bind(target, 'arg1', 'arg2')()
示例一
function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Alice' };// 使用 call 明确指定 this
greet.call(person); // 输出:Hello, Alice
示例二
function greet(city, country) {console.log(`Hello, ${this.name} from ${city}, ${country}`);
}const person = { name: 'Bob' };// 使用 apply,参数是数组
greet.apply(person, ['New York', 'USA']); // 输出:Hello, Bob from New York, USA
示例三
function greet() {console.log(`Hello, ${this.name}`);
}const person = { name: 'Charlie' };// 使用 bind 创建一个新的函数
const boundGreet = greet.bind(person)();// 输出:Hello, Charlie
(4)构造函数和this
function Foo(){this.bar='hist'
}const instance=new Foo()
console.log(instance.bar);//hist
new操作符调用构造函数做了什么?
- 创建一个新的对象
- 将构造函数的this指向这个新对象
- 为这个对象添加属性、方法等
- 最终返回新对象
下面是构造函数中出现显示return的情况,分为两种场景:
function Foo() {this.user = 'hist'const o = {}return o
}const instance = new Foo()
console.log(instance.user);//undefined
将会输出 undefined,此时 instance 是返回的空对象 o。
function Foo() {this.user = 'hist';return 1;
}const instance = new Foo();
console.log(instance.user);//hist
将会输出 hist,也就是说此时 instance 是返回的目标对象实例 this。
结论:如果在构造函数中显式返回一个值,且返回的是一个对象,那么 this 就指向这个返回的对象;如果返回的不是一个对象,那么 this 仍然指向实例。
(5)箭头函数中的this指向
箭头函数和普通函数有一个重要的区别:箭头函数不会有自己的 this,它会继承外部上下文的 this。
const foo = {fn: function () {setTimeout(function () {console.log(this);});},
};
foo.fn();//window
this 出现在 setTimeout() 中的匿名函数里,因此 this 指向 window 对象
const foo = {fn: function () {setTimeout(() => {console.log(this);});},
};foo.fn();//{fn: ƒ}
- 在
foo.fn()
调用时,this
在fn
方法内指向foo
对象。 setTimeout
中的箭头函数继承了外部的this
,也就是foo
对象。
(6)this优先级
通过 call、apply、bind、new 对 this 绑定的情况称为显式绑定
根据调用关系确定的 this 指向称为隐式绑定
function foo(a) {console.log(this.a);
}const obj1 = {a: 1,foo: foo,
};const obj2 = {a: 2,foo: foo,
};obj1.foo.call(obj2); //2
obj2.foo.call(obj1); //1
call、apply 的显式绑定一般来说优先级更高
function foo(a) {this.a = a;
}const obj1 = {};
var bar = foo.bind(obj1);
bar(2);
console.log(obj1.a);
上述代码通过 bind,将 bar 函数中的 this 绑定为 obj1 对象。执行 bar(2) 后,obj1.a 值为 2。即经过 bar(2) 执行后,obj1 对象为:{a: 2}。
当再使用 bar 作为构造函数时:
var baz = new bar(3)
console.log(baz.a)//3
将会输出 3。我们看 bar 函数本身是通过 bind 方法构造的函数,其内部已经将 this 绑定为 obj1,它再作为构造函数,通过 new 调用时,返回的实例已经与 obj1 解绑。 也就是说:new 绑定修改了 bind 绑定中的 this,因此 new 绑定的优先级比显式 bind 绑定更高。
function foo() {return (a) => {console.log(this.a);};
}const obj1 = {a: 1,
};const obj2 = {a: 2,
};const bar = foo.call(obj1);
bar.call(obj2);//1
由于 foo() 的 this 绑定到 obj1,bar(引用箭头函数)的 this 也会绑定到 obj1,箭头函数的绑定无法被修改。
var a = 123;const foo = () => (a) => {console.log(this.a);};const obj1 = {a: 2,};const obj2 = {a: 3,};const bar = foo.call(obj1);console.log(bar.call(obj2));//123
箭头函数的绑定无法被修改,foo的执行上下文是window
如果将第一处的var a = 123;改为const a = 123;
答案将会输出为 undefined,原因是因为使用 const 声明的变量不会挂载到 window 全局对象当中
相关文章:
JS中this的值详细讲解以及面试指向练习
this 的值取决于它出现的上下文:函数、类或全局。 在函数内部,this 的值取决于函数如何被调用,this 是语言在函数体被执行时为你创建的绑定 对于典型的函数,this 的值是函数被访问的对象。换句话说,如果函数调用的形…...
显示浮动式窗口的方法
文章目录 1 概念介绍2 使用方法3 示例代码我们在上一章回中介绍了AlertDialog Widget相关的内容,本章回中将介绍BottomSheet Widget.闲话休提,让我们一起Talk Flutter吧。 1 概念介绍 我们在这里说的BottomSheet是一种弹出式窗口,和上一章回中介绍的AlertDialog类似,但是也…...
FireFox火狐浏览器企业策略禁止更新
一直在用火狐浏览器,但是经常提示更新,进入浏览器右上角就弹出提示,比较烦。多方寻找,一直没有找到合适的方案,毕竟官方没有给出禁用检查更新的选项,甚至about:config里都没有。 最终找到了通过企业策略控…...
C++类的运算符重载
目标 让自定义的类直接使用运算符运算 代码 头文件及类定义 #include <iostream>using namespace std; class Complex {int rel;int vir; public:void show(){cout <<"("<<this->rel<<","<<this->vir<<&quo…...
泷羽Sec学习笔记-zmap搭建炮台
zmap搭建炮台 zmap扫描环境:kali-linux 先更新软件库 sudo apt update 下载zmap sudo apt install zmap 开始扫描(需要root权限) sudo zmap -p 80 -o raw_ips.txt 代码解析: sudo:以超级用户(管理员)权限运行…...
分析M0G突破后急剧下跌内因,x.game阐述不利面延续多久
MOG最新消息显示,美国唐纳德-的一则声明公开表示支持一种基于以太坊网络ERC-20代币标准的病毒式meme代币——Mog Coin(MOG),这一消息迅速发酵。然而,令人意想不到的是,在这位全球知名政治人物的背书之后&am…...
网络爬虫全解析
一、网络爬虫基础要点 (一)爬虫原理 目标确定:明确需要抓取数据的网站或网页范围,例如针对特定电商平台抓取商品信息,或聚焦新闻网站获取新闻报道内容,要考量数据的价值与用途。URL 解析:理解网…...
《孤岛惊魂4》无法启动提示缺少“msvcp100.dll”快速修复方法!
《孤岛惊魂4》缺少msvcp100.dll的解决之道 在探索《孤岛惊魂4》这款充满惊险与刺激的射击游戏时,玩家可能会遇到一些意外的障碍,其中之一便是“缺少msvcp100.dll”的错误提示。这个错误不仅让游戏无法正常启动,还可能让玩家对游戏的热情大打…...
GS-SLAM论文阅读--RGBDS-SLAM
前言 最近GS-SLAM领域的工作层出不穷,有很多不错的工作出现。接下来慢慢写一下相关博客。 文章目录 前言1.背景介绍2.关键内容2.1 3D多层次金字塔高斯喷溅2.2 紧密耦合多特征重构优化2.3总体流程 3.文章贡献4.个人思考 1.背景介绍 高保真重建是密集SLAM的关键。最…...
条件编译->enable_if和 if constexpr使用区别
enable_if 和 if constexpr 是 C 中用于控制编译或运行时条件的重要工具,它们各有不同的用途和使用场景。以下是它们的主要区别: 1. enable_if std::enable_if 是一个类型特征,用于在编译时根据条件选择类型。常用于模板元编程,…...
介绍一下CSS中伪类和伪元素的概念
一、伪类(Pseudo - Classes) 1. 定义 伪类是添加到选择器的关键字,用于定义元素的特殊状态。这些状态不是由文档树中的结构或属性来表示,而是基于用户行为(如鼠标悬停)、元素状态(如被选中&am…...
【橘子ES】熔断器Circuit breaker
一、相关概念 我们在日常的开发中,关于服务之间的熔断操作似乎很常见,当请求超过了我们服务所认为可以承受的一个上限阈值的时候,我们为了保护服务不会被进一步的高负载压崩溃,我们有时候会选择熔断请求,此时服务不再…...
6.4 CPU性能分析--Intel处理器跟踪技术
Intel处理器跟踪PT技术是记录程序执行过程的技术,它把记录信息编码报文存到高压缩率的二进制文件中。该二进制文件结合每条指令的时间戳重建执行流。PT技术覆盖度大,开销小,有关开销的信息详见,主要用于性能问题的事后分析和根因定…...
期权懂|如何用第三方平台开通期权?
期权小懂每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 如何用第三方平台开通期权? 如果不能满足常规的期权开户条件,可以考虑以下几种方法来尝试开户: 一、选择第三方平台: 通过网络搜…...
JS中const有没有变量提升
在JavaScript中,const 关键字用于声明一个只读的常量,其值在初始化后不能被重新赋值。关于变量提升(Hoisting),它是JavaScript中一个重要的概念,指的是无论变量或函数声明在何处,它们都会被“提…...
Axure RP全面介绍:功能、应用与中文替代方案
Axure RP是一款功能强大的原型设计工具,它被广泛应用于网页和移动应用的设计领域。Axure RP集成了设计、原型制作和文档管理,为产品管理人员、设计师和开发人员提供了一个综合的平台。让我们一步步了解Axure的基本功能、使用技巧以及中文支持平台——“在…...
WordPress用户首次登录强制修改密码
有些企业网站要求很高,比如用户首次登录强制要求修改密码,这里提供一段代码,用于实现强制修改密码供参考。 通过代码可以实现,用户正常注册或者管理员在后台添加用户时,会添加首次登录标记,用户首次登录后会…...
AI开源南京分享会回顾录
AI 开源南京分享会,已于2024年11月30日下午在国浩律师(南京)事务所5楼会议厅成功举办。此次活动由 KCC南京、PowerData、RISC-Verse 联合主办,国浩律师(南京)事务所协办。 活动以“开源视角的 AI 对话”为主…...
基于事件驱动的websocket简单实现
websocket的实现 什么是websocket? WebSocket 是一种网络通信协议,旨在为客户端和服务器之间提供全双工、实时的通信通道。它是在 HTML5 规范中引入的,可以让浏览器与服务器进行持久化连接,以便实现低延迟的数据交换。 WebSock…...
【leetcode100】反转链表
1、题目描述 给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。 示例 1: 输入:head [1,2,3,4,5] 输出:[5,4,3,2,1] 2、初始思路 2.1 思路 # Definition for singly-linked list. # class ListNode: # …...
禅道Bug的一次迁移
一、场景 平时工作记录在公司禅道上的问题想备份一份到本地,但是又没有公司禅道的数据库信息,有时候出测试报告想批量调整数据方便截图很困难,同时也为了学习禅道数据流转过程,所以有了把缺陷保存到本地一份的想法。 实际上禅道支…...
c段和旁站讲解(附查询网址)
1. C段(C类子网段) C段就是一个IP地址的小范围。比如,假设你有一个家庭Wi-Fi网络,Wi-Fi会分配给你一组IP地址(每个设备一个IP地址)。如果你的网络分配的是类似 192.168.1.0 这样的IP地址,那么这…...
Linux编译Kernel时的文件zImage、文件dtb(dtbs)、核心模块分别是什么东西?
zImage文件的介绍 在编译Linux内核时,zImage 是一种内核映像文件,它是内核的压缩版本,通常用于引导嵌入式设备或其他资源有限的环境。 zImage 的具体含义 zImage 是 “Compressed Kernel Image” 的缩写。它是通过压缩原始的内核映像&…...
【深度学习】深刻理解“变形金刚”——Transformer
Transformer 是一种用于处理序列数据的深度学习模型架构,最初由 Vaswani 等人在 2017 年的论文《Attention is All You Need》中提出。它彻底改变了自然语言处理(NLP)领域,成为许多高级任务(如机器翻译、文本生成、问答…...
75_pandas.DataFrame 中查看和复制
75_pandas.DataFrame 中查看和复制 与pandas的DataFrame与NumPy数组ndarray类似,也有视图(view)和拷贝(copy)。 当使用loc[]或iloc[]等选择DataFrame的一部分以生成新的DataFrame时,与原对象共享内存的对…...
打电话玩手机识别-支持YOLO,COCO,VOC格式的标记,超高识别率可检测到手持打电话, 非接触式打电话,玩手机自拍等
打电话玩手机识别-支持YOLO,COCO,VOC格式的标记,超高识别率可检测到手持打电话, 非接触式打电话,玩手机自拍等1275个图片。 手持打电话: 非接触打电话 玩手机 数据集下载 yolov11:https://download.csdn…...
生产慎用之调试日志对空间矢量数据批量插入的性能影响-以MybatisPlus为例
目录 前言 一、一些缘由 1、性能分析 二、插入方式调整 1、批量插入的实现 2、MP的批量插入实现 3、日志的配置 三、默认处理方式 1、基础程序代码 2、执行情况 四、提升调试日志等级 1、在logback中进行设置 2、提升后的效果 五、总结 前言 在现代软件开发中,性能优…...
单片机:实现倒计时(附带源码)
使用单片机实现倒计时功能是一个常见的嵌入式应用,它能帮助你更好地理解如何进行时间控制和如何通过定时器实现精确的倒计时。通过该项目,你将学习如何使用单片机的定时器来进行时间计算,并通过LED或LCD显示倒计时的结果。 1. 项目概述 倒计…...
什么是多线程中的上下文切换
什么是多线程中的上下文切换 回答 上下文切换是指CPU从一个线程转到另一个线程时,需要保存当前线程的上下文状态,恢复另一个线程的上下文状态,以便于下一次恢复执行该线程时能够正确地运行。 在多线程编程中,上下文切换是一种常…...
如何在windwos批量拉取go mod
golang go-zero微服务开发,分的rpc项目太多了,变更了公共包,需要手动去拉取,直接一键拉取就好了,创建一个windwos脚本文件 文件名 tidy_all_go_mod.ps1 代码 # 辅助工具拉取go mod tidy # 根目录v99main执行 ./tidy_all_go_mod.ps1 # 定义项目的根目录 $RootDir Get-Locat…...
ota平台网站建设/深圳seo优化排名推广
AdaGrad中的Ada是Adaptive之意,即“自适应的”,什么自适应呢,这里是指NN中的学习率,可以自适应的调整,并且是每一个参数有自己专门的调整,不是全体参数的学习率同时调整(共享一个学习率…...
郑州治疗精神病哪家好/河南seo推广
过几天小弟要去面试了,当然免不了要好好复习下功课,其实很多东西也不是特别清楚,今天都当作一个回顾和巩固,希望我的这篇文章能对即将去找工作的同学有所帮助。 1. Q:什么是activity? 虽然这个问题现在不流…...
毕业设计做的网站抄袭/谷歌浏览器官网
文章目录简介使用相机前的准备工作在flutter中使用camera总结简介 在app中使用相机肯定是再平常不过的一项事情了,相机肯定涉及到了底层原生代码的调用,那么在flutter中如何快速简单的使用上相机的功能呢? 一起来看看吧。 使用相机前的准备…...
万网wordpress安装教程/百度秒收录技术
观察以下代码结果,为什么? 原因是因为:运算数类型整形除整形结果还是整形,计算机中float和double都是IEEE754标准 1记录浮点数的,以上代码中得到的值是3,转化为IEEE754标准值就是0.0000000 解决办法1&…...
自己如何搭建网站/微信营销软件排行榜
转自https://www.cnblogs.com/subconscious/p/4660952.html 一.前言 今天继续我们EasyPR的开发详解。 这几个月我收到了不少的邮件问:为什么EasyPR开发详解教程中只有车牌定位的部分,而没有字符识别的部分? 这个原因一是由于整个开发详解是按…...
网站改版后seo该怎么做/衡阳网站建设公司
1. 概述 在《Apollo 极简入门》中,我们已经学习了如何搭建一个 Apollo 服务。如果还没有的胖友,赶紧先去简单学习下,重点是跟着该文「2. 单机部署」小节,自己搭建一个 Apollo 服务。 本文,我们来学习下如何在 Spring…...