JS中的闭包和上下文

在这里插入图片描述

变量提升 和 函数提升

这里要提到一个提升的概念,即在JS中,在解析代码之前还有一个预处理的过程,这个过程中会把部分变量和函数声明提前到代码的最顶部,
会在其他所有代码之前执行。虽然当我们按照规范(严格模式或者TS等良好的编码习惯)时并不会因为提升而发生意料之外的情况,不过作为原生
JS中的特性,我们还是需要了解一下。

函数提升

还记得在C语言中,我们往往会把函数签名的声明提前都放到文件的最前面,然后实现放在main函数后面吗?这就是因为函数要先声明后使用,而在
JS中,解析器已经帮我们做好了这件事情,所以我们在使用函数的时候不需要提前声明它,解析器会帮我们自动把函数声明提前到代码的最顶部。不过
需要说明的是这种提升只对声明后的函数有效(比如这种形式:function xxxx()),而对于函数表达式(let fun = function(){})则不会有提升效果。

变量提升

当我们使用var关键字声明变量的时候就会产生变量提升的效果,这带来的效果就是即使我们先使用某个变量然后再声明它也不会报错,
因为变量声明会被提前到代码的最顶部:

console.log(nameless);
var nameless = 'hello';

这样写是不会报错的,但是会打印出undefined,因为虽然声明提前来但是赋值并没有提前,所以在声明复制之前nameless的值就是undefined了。

这里还有一种情况,那就是我们同时声明了一个变量和一个函数,且他们的名称相同,这个时候只会提升他们的其中之一,并且函数的提升优先级是高于
变量的提升的
。不过现在我们应该遇不到这种情况了,因为这会在控制台中输出错误提醒我们。

建议

总而言之,建议我们还是使用ES6中的letconst关键字来声明变量和常量,因为这样可以避免变量提升带来的问题。最好的情况是直接使用
TypeScript,它提供的编译阶段检查可以帮助我们避免一些错误。

执行期上下文 和 this的指向

所谓执行期上下文,这个函数执行时的环境。在那些面向对象的编程语言中,我们可以把函数在哪里被定义的类的实例作为上下文来看,我觉得在
JS中也可以这样类比,不过不同的是JS中类的存在感比较低,常常一个函数被定义在一个object中,可以把他视作是一个匿名类的实例。

比如说我们有这么一个函数:

function anchor() {let count = 0;return {add: function () {console.log(`add anchor:${this.count++}`)},remove: function () {console.log(`remove anchor${this.count--}`)},printInfo: function () {console.log(`anchor count:${this}`)}}
}const anchorInstance = anchor();
anchorInstance.add();
anchorInstance.add();
anchorInstance.printInfo();

这个函数会返回一个对象,这个对象有三个方法,分别是增加this的count、减少this的count和打印this的指向。
当我们获得这个对象直接调用add或remove方法时:

add anchor:NaN
add anchor:NaN
anchor count:[object Object]

可以看到count的值是不正确的,我们更直观一点,直接打印count的值的话可以发现打印出来的是 undefined ,虽然我们在anchor函数中定义了count,
但是this.count并不会指向它,它指向的是所在对象的count,而所在对象中又没有定义count,所以就打印不出来了。当我们给这个对象加上count属性
后就可以正常打印了:

//调用
anchorInstance.count = 0;
anchorInstance.add();
anchorInstance.add();
anchorInstance.printInfo();
//结果:
// add anchor:0
// add anchor:1
// anchor count:[object Object]

这里我们再改动一下,把this关键字去掉结果发现也能正确打印信息。它正确使用到了anchor函数的局部变量,这实际上就产生了函数闭包。第二个原因就
是函数的作用域链,在嵌套的函数之中,变量会从内到外逐层寻找它的定义(就近原则),通过这种原则来决定取哪个值。当我们没有指定count的所在时,就会
根据作用域链向外寻找count变量。

除此之外,还需要注意的是关于箭头函数的this指向,匿名函数的this指向的是他的调用者,而箭头函数的this指向的是定义时寻找到的变量。这在
我们设置了原型的时候需要格外注意。

函数闭包

所谓闭包的意思就是函数内部的局部变量被外部持有了,类似于JVM中的可达性算法,由于这个变量被外部持有,也就是说正在被外部使用(不考虑内存泄漏)
那系统肯定不能把这个变量销毁,从而延长了函数局部变量的生命。

闭包在JavaScript中也有他的应用场景:

  • 数据封装和私有化
  • 作为函数工厂
  • 保留/追踪 函数的执行信息
  • 异步编程中(同步方式写异步)

上面的anchor函数中,我们使用的就是第一个应用场景,我们把count变量封装在了函数内部,外部只能通过return的接口来操作这个变量。

除此之外我觉得比较有用的就是追踪函数的执行信息了,比如我们可以封装这么一个函数:

let SecurityReporter = function() {let invokedInfos = [];return {connectDatabase() {const invokeInfo = {invokedTime : new Date(),invokedMethod : "[connect Database]"}invokedInfos.push(invokeInfo);},disconnectDatabase() {const invokeInfo = {invokedTime : new Date(),invokedMethod : "[disconnect Database]"}invokedInfos.push(invokeInfo);},reportInfos() {console.log(invokedInfos);}};
}const securityReporterIns = SecurityReporter();
securityReporterIns.connectDatabase();
securityReporterIns.disconnectDatabase();
securityReporterIns.reportInfos();

我们构建了一个类似于埋点上报的系统,当我们调用方法时就会自动把相关信息存储到一个闭包中,方便我们整理和排查日志。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/890973.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

从百度云网盘下载数据到矩池云网盘或者服务器内

本教程教大家如何快速将百度云网盘数据集或者模型代码文件下载到矩池云网盘或者服务器硬盘上。 本教程使用到了一个开源工具 BaiduPCS-Go,官方地址 : https://github.com/qjfoidnh/BaiduPCS-Go 这个工具可以实现“仿 Linux shell 文件处理命令的百度网…

基于Fastapi搭建API服务实践案例

文章目录 前言服务框架结构app.pyrun_app_server.shrouters/upload.pyrouters/query_result.pyutils/utils.pyutils/tasks.py 总结 前言 本文讲述了如何使用fastapi搭建一个属于自己的服务,整个服务使用fastapi框架搭建,celery管理任务队列,…

【每日学点鸿蒙知识】hvigor升级、Dialog动画、LocalStorage无效、页面与子组件的生命周期、cookie设置

1、HarmonyOS 编译工具hvigor如何升级到"hvigorVersion": "4.2.0"版本? 可以手动更新到指定版本,参考链接如下:https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/ide-hvigor-plugin-V5 2、HarmonyOS…

【AI学习】DeepSeek-V3 技术报告学习:总体架构

翻了一下DeepSeek-V3 技术报告学习,太长,只是大概翻了一下,其中Multi-Token Prediction的技术就很亮眼。 摘要 本文介绍了DeepSeek-V3,这是一个拥有671B总参数的强大混合专家(MoE)语言模型,每…

总结-常见缓存替换算法

缓存替换算法 1. 总结 1. 总结 常见的缓存替换算法除了FIFO、LRU和LFU还有下面几种: 算法优点缺点适用场景FIFO简单实现可能移除重要数据嵌入式系统,简单场景LRU局部性原理良好维护成本高,占用更多存储空间内存管理,浏览器缓存L…

手机联系人 查询 添加操作

Android——添加联系人_android 添加联系人-CSDN博客 上面连接添加联系人已测试 是可以 Android : 获取、添加、手机联系人-ContentResolver简单应用_contentresolver 添加联系人-CSDN博客

【黑马头条训练营】day01-黑马头条整体构成与App登录

目录 描述app端从登录请求到首页显示的全部流程 描述用户微服务的组成及登录业务及实现逻辑 自己编写用户微服务登录关键逻辑 描述app端从登录请求到首页显示的全部流程 从浏览器发起请求访问app前端 通过nginx请求到我们app前端 在app端我们输入手机号及密码登录 发起请求…

一文大白话讲清楚javascript浮点数精度丢失和解决策略

文章目录 一文大白话讲清楚javascript浮点数精度丢失和解决策略1.问题的来源北京2. 浮点数的存储二进制存储3.精度丢失解决方案 一文大白话讲清楚javascript浮点数精度丢失和解决策略 1.问题的来源北京 我们先看一个经典javascript问题,关于等值判断 let num0.10…

C语言-数据结构-图

目录 一,图的概念 1,图的定义 2,图的基本术语 二,图的存储结构 1,邻接矩阵 2,邻接表 三,图的遍历 1,深度优先搜索 2,广度优先搜素 四,生成树和最小生成树 1,生成树的特点: 2,最小生成树 (1)普利姆算法Prim (2)普里姆算法思路 五,最短路径 1,Dijkstra算法 2,Fl…

C语言-数据结构-查找

目录 一,查找的概念 二,线性查找 1,顺序查找 2,折半查找 3,分块查找 三,树表的查找 1,二叉排序树 (1)查找方式: (2)、二叉排序树的插入和生成 (3)、二叉排序树的删除 2,平衡二叉树 (1)、什么是平衡二叉树 (2)、平衡二叉树的插入调整 (1)L…

【微信小程序】4plus|搜索框-历史搜索 | 我的咖啡店-综合实训

升级版1-清空全部的再次确认 实现功能: 历史搜索记录展示-历史搜索记录展示10条点击跳转-点击历史搜索记录可同步到搜索框并自动搜索全部删除-可一次性全部删除历史搜索记录全部删除-有再次确认操作展示 进行搜索后留下搜索记录 点击垃圾桶图标,显示【清空全部】 点击【清…

线程池基础知识

线程池: 顾名思义就是管理一系列线程的资源池。当有任务要处理时,直接从线程池中获取线程来处理,处理完之后线程并不会立即被销毁,而是等待下一个任务。 使用线程池的好处 降低资源消耗:通过重复利用已创建的线程降…

ARM 架构--通用寄存器状态寄存器控制寄存器特殊用途寄存器

目录 一?ARM 架构中的寄存器 ARM 架构中的寄存器 通用寄存器 状态寄存器 控制寄存器 特殊用途寄存器 总结 二 通用寄存器 ARM 架构中的通用寄存器 ARMv7 架构 ARMv8 架构 实例 ARMv7 架构 ARMv8 架构 三 状态寄存器 ARM 架构中的状态寄存器 状态寄存器 详细…

macrodroid通过http请求控制手机运行宏

macrodroid adb命令 adb shell pm grant com.arlosoft.macrodroid android.permission.WRITE_SECURE_SETTINGS例:http请求手机播放指定MP3文件 声音素材_电量过低提醒 新建一个宏 添加触发器-连接-http服务器请求 路径随意填,最好不要有特殊符号,不然浏览器识别链接会出错,…

【CSS in Depth 2 精译_098】17.3:CSS 动画延迟技术与填充模式设置 + 17.4:通过 CSS 动画传递意图的秘诀

当前内容所在位置(可进入专栏查看其他译好的章节内容) 第五部分 添加动效 ✔️【第 17 章 动画】 ✔️ 17.1 关键帧17.2 3D 变换下的动画设置 17.2.1 添加动画前页面布局的构建17.2.2 为布局添加动画 17.3 动画延迟与填充模式 ✔️17.4 通过动画传递意图…

慧集通客户案例:致远OA与熵基考勤机集成方案

本原型公司是一家专注大健康产业的综合性高新科技形实体企业,按照单位的战略业务布局,围绕“做强做优、世界一流”的目标,加快内外部资源整合、加强业务协同、优化资源配置,有序推进大健康及相关产业的有机融合,加快构…

深度学习笔记(6)——循环神经网络RNN

循环神经网络 RNN 核心思想:RNN内部有一个“内部状态”,随着序列处理而更新 h t f W ( h t − 1 , x t ) h_tf_W(h_{t-1},x_t) ht​fW​(ht−1​,xt​) h t h_t ht​是new state, h t − 1 h_{t-1} ht−1​是old state, x t x_t xt​是当前时间步的输入,所有时间步共享 f W…

电脑卡顿救星,Mem Reduct 智能清理 10%以上内存

作为一款专业的内存优化工具,Mem Reduct凭借其强大的功能和极致的性能表现,成为众多用户管理系统内存的首选软件。它采用先进的内存管理算法,通过调用系统底层API接口,能够智能识别并清理各类内存占用,包括但不限于系统…

kibana启动报错:Invalid character in header content [“kbn-name“]

启动时候kibana报错: 打开 kibana配置文件,config/kibana.yml,配置上server.name即可,如下:

短视频矩阵系统后端源码搭建实战与技术详解,支持OEM

一、引言 随着短视频行业的蓬勃发展,短视频矩阵系统成为了众多企业和创作者进行多平台内容运营的有力工具。后端作为整个系统的核心支撑,负责处理复杂的业务逻辑、数据存储与交互,其搭建的质量直接影响着系统的性能、稳定性和可扩展性。本文将…