【面试题】闭包是什么?this 到底指向谁?

一通百通,其实函数执行上下文、作用域链、闭包、this、箭头函数是相互关联的,他们的特性并不是孤立的,而是相通的。因为内部函数可以访问外层函数的变量,所以才有了闭包的现象。箭头函数内没有 this 和 arguments,所以内部调用了 this,会去上层函数作用域中查找 this 的指向。这些内容都是相通的。我们要融会贯通全面理解,而不是死记硬背哦。
大厂面试题分享 面试题库
前后端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
变量定义
var 声明变量
变量未声明直接使用
这两种方式都可以声明变量,但是该变量会是全局变量,绑定在 window 对象上。同时 var 会有声明提升的作用。
console.log(a); // undefined;并不会报错var a;
复制代码
let 声明变量
const 声明变量
let 和 const 是 ES6 新增的关键字,let 和 const 声明的变量不会有声明提前的特点。同时,let 和 const 声明之前的执行瞬间被称为”暂时性死区“,在此阶段引用任何后面才声明的变量都会抛出 ReferenceError。
let 和 const 在全局作用域中声明的变量不会成为 window 对象的属性。
const 声明变量时必须同时初始化变量。
最佳实践:
不使用 var
const 优先,let 次之
函数定义
与变量不同,函数定义会提前;变量只是声明提前。
say() // Hello worldfunctionsay(){console.log('Hello world')}
复制代码
但是使用变量声明函数,函数定义不会提前,同 var 变量声明一样,只是声明会提前。
console.log(say) // undefinedvar say = function(){console.log('Hello world')}
复制代码
原因是在执行 js 代码之前会进行变量提升和函数定义。
函数执行
作用域 规定了如何查找变量,也就是确定当前执行代码对变量的访问权限。
执行上下文:当我们执行一个方法时,JavaScript 会生成一个与这个方法对应的执行环境(context),又叫执行上下文。这个执行环境中有这个方法的私有作用域、上层作用域的指向、方法的参数(arguments)、私有作用域中定义的变量以及 this 对象。这个执行环境被添加到一个栈中,这个栈就是执行栈。
如果在这个方法的代码中执行到了一行函数调用语句,那么 JavaScript 会生成这个函数的执行环境并将其添加到执行栈中,然后进入这个执行环境继续执行其中的代码。执行完毕后返回结果后,JavaScript 会退出执行环境并把这个执行环境从栈中销毁,回到上一个方法的执行环境。这个过程反复进行,直到执行栈中的代码全部执行完毕。这个执行环境的栈就是执行栈。
执行上下文分全局上下文、函数上下文和块级上下文。
内层函数 fn 内有 arguments 对象、 this 对象、变量;以及函数 Fn 上层作用域的指向。fn 可以访问上层 Fn 的变量,但是不能访问 Fn 的 this 和 arguments 对象。
JavaScript 采用词法作用域,也就是静态作用域。
var value = 1;functionfoo() {console.log(value);
}functionbar() {var value = 2;foo();
}bar();
复制代码
JavaScript采用的是词法作用域,函数的作用域基于函数创建的位置。
块级作用域(ES6新增)
for(let i=0;i<10;i++){// i 只能在这里使用
}
复制代码
functionf(flag){if(flag){var x = 10;}return x;
}
console.log(f(false)); //不会报错, undefined复制代码
闭包和 this
闭包(closure)指的是那些引用了另一个函数作用域中变量的函数,通常是在嵌套函数中实现的。注意:只有引用了另一个函数作用域中的变量,才称为闭包,如果一个函数 A 内部返回了另一个函数 B,内部函数 B 并没有引用 A 的作用域中的变量是不会形成闭包的。博客
javascript - 理解闭包与内存泄漏 - 前海拾贝 - SegmentFault 思否 已验证。
闭包和执行上下文以及作用域是相通的,那就是内部函数可以访问外部函数的变量,但是不能访问外部函数的 this 和 arguments 对象。如下的例子:
window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'returnfunction() {console.log(code)returnthis.identity;};}
};
console.log(object.getIdentityFunc()()); // 'The Window'复制代码
第6行的匿名函数调用了外部函数 getIdentityFunc 函数作用域中的变量 code,我们称之为闭包,由于内部函数并不能访问外部函数的 this 和 arguments 对象,所以 this 对象并不是 object , 而是全局函数的 this window。

对于普通函数调用时的 this 指向:在全局函数中调用 this,this 等于 window;如果作为某个对象的方法调用,则 this 等于这个对象。先判断谁调用了这个函数,然后再判断 this 指向。
对于箭头函数 this 指向:因为箭头函数内部没有 this 和 arguments 对象,所以箭头函数的 this 指向该函数所在的作用域指向的对象。符合作用域查找逻辑,箭头函数本身没有 this 定义,会沿着作用域链查找。这时的 this 相当于一个变量,按照词法作用域逻辑查找。修改上面的例子:
window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'return() => {console.log(code)returnthis.identity;};}
};
console.log(object.getIdentityFunc()()); // 'My Object'复制代码
此时,内部函数修改为箭头函数,我们知道箭头函数内部没有自己的 this,所以会沿着作用域链查找上层函数 getIdentityFunc 的 this 指向。由于是 object 调用的 getIdentityFunc,所以 getIdentityFunc 的 this 指向 object 对象。再复杂一点:
window.identity = 'The Window';
let object = {identity: 'My Object',getIdentityFunc() {let code = 'closure'return() => {console.log(code)returnthis.identity;};}
};
const callObject = {identity: 'call object'}
console.log(object.getIdentityFunc.call(callObject)()); // 'call object'复制代码
这里调用的时候,使用了 call 改变了 getIdentityFunc 了 this 指向 callObject, 那么箭头函数在调用的时候,会沿着作用域链找到 getIdentityFunc 的 this 指向为 callObject 对象。
大厂面试题分享 面试题库
前后端面试题库 (面试必备) 推荐:★★★★★
地址:前端面试题库
相关文章:

【面试题】闭包是什么?this 到底指向谁?
一通百通,其实函数执行上下文、作用域链、闭包、this、箭头函数是相互关联的,他们的特性并不是孤立的,而是相通的。因为内部函数可以访问外层函数的变量,所以才有了闭包的现象。箭头函数内没有 this 和 arguments,所以…...

汽车4S店业务管理软件
一、产品简介 它主要提供给汽车4S商店,用于管理各种业务,如汽车销售、售后服务、配件、精品和保险。整个系统以客户为中心,以财务为基础,覆盖4S商店的每一个业务环节,不仅可以提高服务效率和客户满意度,…...

基于 pytorch 的手写 transformer + tokenizer
先放出 transformer 的整体结构图,以便复习,接下来就一个模块一个模块的实现它。 1. Embedding Embedding 部分主要由两部分组成,即 Input Embedding 和 Positional Encoding,位置编码记录了每一个词出现的位置。通过加入位置编码可以提高模型的准确率,因为同一个词出现在…...

算法小抄6-二分查找
二分查找,又名折半查找,其搜索过程如下: 从数组中间的元素开始,如果元素刚好是要查找的元素,则搜索过程结束如果搜索元素大于或小于中间元素,则排除掉不符合条件的那一半元素,在剩下的数组中进行查找由于每次需要排除掉一半不符合要求的元素,这需要数组是已经排好序的或者是有…...

大学四年..就混了毕业证的我,出社会深感无力..辞去工作,从头开始
时间如白驹过隙,一恍就到了2023年,今天最于我来说是一个值得纪念的日子,因为我收获了今年的第一个offer背景18年毕业,二本。大学四年,也就将就混了毕业证和学位证。毕业后,并未想过留在湖南,就回…...

C语言数据结构初阶(6)----链表常见OJ题
CSDN的uu们,大家好!编程能力的提高不仅需要学习新的知识,还需要大量的练习。所以,C语言数据结构初阶的第六讲邀请uu们一起来看看链表的常见oj题目。移除链表元素原题链接:203. 移除链表元素 - 力扣(Leetcod…...
关键字 const
目录 一、符号常量与常变量 二、const的用法 2.1 const常用方法 2.2 const用于指针 2.2.1 p指针所指的对象值不能改变,但是p指针的指向可以改变 2.2.2 常指针p的指向不能改变,但是所指的对象的值可以改变 2.2.3 p所指对象的指向以及对象的值都不可…...

MybatisPlus------MyBatisX插件:快速生成代码以及快速生成CRUD(十二)
MybatisPlus------MyBatisX插件(十二) MyBatisX插件是IDEA插件,如果想要使用它,那么首先需要在IDEA中进行安装。 安装插件 搜索"MyBatisX",点击Install,之后重启IDEA即可。 插件基本用途&…...

Leetcode138. 复制带随机指针的链表
复制带随机指针的链表 第一步 拷贝节点链接在原节点的后面 第二步拷贝原节点的random , 拷贝节点的 random 在原节点 random 的 next 第三步 将拷贝的节点尾插到一个新链表 ,并且将原链表恢复 从前往后遍历链表 ,将原链表的每个节点进行复制,并l链接到原…...

python并发编程多线程
在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 线程顾名思义,就是一条流水线工作的过程,一条流水线必须属于一个车间,一个车间的工作过程是一个进程 车间负责把资源整合到一起,是一个…...

使用Maven实现Servlet程序
创建Maven项目我们打开idea的新建项目,选中里面Maven即可,如下图:创建完成之后,会看到这样的目录结构其中,main目录存放业务代码,其中的java目录存放的就是java代码,而resources目录存放是程序中依赖的文件,比如:图片,视频等.然后是 test目录,test目录存放的是测试代码.最后一个…...

百度的文心一言 ,没有想像中那么差
robin 的演示 我们用 robin 的演示例子来对比一下 文心一言和 ChatGPT 的真实表现(毕竟发布会上是录的)。 注意,我使用的 GPT 版本是 4.0 文学创作 1 三体的作者是哪里人? 文心一言: ChatGPT: 嗯&a…...
文心一言发布的个人看法
文心一言发布宣传视频按照发布会上说的,文心一言并非属于百度赶工抄袭Chat-GPT的作品,而是十几年一直布局AI产业厚积薄发的成果,百度在芯片,机器学习,自然语言处理,知识图谱等方面均有相对深厚的积累。 国…...

【C5】111
文章目录bmc_wtd:syscpld.c中wd_en和wd_kick节点对应寄存器,crontab,FUNCNAMEAST2500/2600 WDT切换主备:BMC用WDT2作为主备切换的watchdog控制器AC后读取:bmc处于主primary flash(设完后:实际主…...
静态成员,友元函数
🐶博主主页:ᰔᩚ. 一怀明月ꦿ ❤️🔥专栏系列:线性代数,C初学者入门训练,题解C,C的使用文章,「初学」C 🔥座右铭:“不要等到什么都没有了,才下…...
数学分析课程笔记(张平):函数
01 函数 \quad作为数学分析的第一节课,首先深入了解一下函数。 \quad翻看一些教材可以发现,有些教材将“函数”与“映射”区分为两个概念,有些教材(尤其是前苏联时期的一些教材)则将其视为一个概念。实际上,…...
spring事务 只读此文
文章目录一. 事务概述1.1. MySQL 数据库事务1.2 spring的事务支持:1.2.1 编程式事务:1.2.2 声明式事务1.2.3 事务传播行为:1.2.4 事务隔离级别1.2.5 事务的超时时间1.2.6 事务的只读属性1.2.7 事务的回滚策略二. spring事务(注解 Transaction…...

真实的软件测试日常工作是咋样的?
最近很多粉丝问我,小姐姐,现在大环境不景气,传统行业不好做了,想转行软件测试,想知道软件测试日常工作是咋样的?平常的工作内容是什么? 别急,今天跟大家细细说一下一个合格的软件测…...

【UML】软件需求说明书
目录🦁 故事的开端一. 🦁 引言1.1编写目的1.2背景1.3定义1.4参考资料二. 🦁 任务概述2.1目标2.2用户的特点2.3假定和约束三. 🦁 需求规定3.1 功能性需求3.1.1系统用例图3.1.2用户登录用例3.1.3学员注册用例3.1.4 学员修改个人信息…...
面试官:html里面哪个元素可以让文字换行展示
在HTML中,可以使用 <br> 元素来强制换行,也可以使用CSS的 word-break 或 white-space 属性来实现自动换行。以下是这些方法的具体说明: 1.使用 <br> 元素 <br> 元素可以在文本中插入一个换行符,使文本从该位置…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

深入剖析AI大模型:大模型时代的 Prompt 工程全解析
今天聊的内容,我认为是AI开发里面非常重要的内容。它在AI开发里无处不在,当你对 AI 助手说 "用李白的风格写一首关于人工智能的诗",或者让翻译模型 "将这段合同翻译成商务日语" 时,输入的这句话就是 Prompt。…...

成都鼎讯硬核科技!雷达目标与干扰模拟器,以卓越性能制胜电磁频谱战
在现代战争中,电磁频谱已成为继陆、海、空、天之后的 “第五维战场”,雷达作为电磁频谱领域的关键装备,其干扰与抗干扰能力的较量,直接影响着战争的胜负走向。由成都鼎讯科技匠心打造的雷达目标与干扰模拟器,凭借数字射…...
力扣-35.搜索插入位置
题目描述 给定一个排序数组和一个目标值,在数组中找到目标值,并返回其索引。如果目标值不存在于数组中,返回它将会被按顺序插入的位置。 请必须使用时间复杂度为 O(log n) 的算法。 class Solution {public int searchInsert(int[] nums, …...

ABAP设计模式之---“简单设计原则(Simple Design)”
“Simple Design”(简单设计)是软件开发中的一个重要理念,倡导以最简单的方式实现软件功能,以确保代码清晰易懂、易维护,并在项目需求变化时能够快速适应。 其核心目标是避免复杂和过度设计,遵循“让事情保…...
Java 二维码
Java 二维码 **技术:**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

RabbitMQ入门4.1.0版本(基于java、SpringBoot操作)
RabbitMQ 一、RabbitMQ概述 RabbitMQ RabbitMQ最初由LShift和CohesiveFT于2007年开发,后来由Pivotal Software Inc.(现为VMware子公司)接管。RabbitMQ 是一个开源的消息代理和队列服务器,用 Erlang 语言编写。广泛应用于各种分布…...

GO协程(Goroutine)问题总结
在使用Go语言来编写代码时,遇到的一些问题总结一下 [参考文档]:https://www.topgoer.com/%E5%B9%B6%E5%8F%91%E7%BC%96%E7%A8%8B/goroutine.html 1. main()函数默认的Goroutine 场景再现: 今天在看到这个教程的时候,在自己的电…...
学习一下用鸿蒙DevEco Studio HarmonyOS5实现百度地图
在鸿蒙(HarmonyOS5)中集成百度地图,可以通过以下步骤和技术方案实现。结合鸿蒙的分布式能力和百度地图的API,可以构建跨设备的定位、导航和地图展示功能。 1. 鸿蒙环境准备 开发工具:下载安装 De…...

PydanticAI快速入门示例
参考链接:https://ai.pydantic.dev/#why-use-pydanticai 示例代码 from pydantic_ai import Agent from pydantic_ai.models.openai import OpenAIModel from pydantic_ai.providers.openai import OpenAIProvider# 配置使用阿里云通义千问模型 model OpenAIMode…...