JavaScript的作用域与闭包
文章目录
- 一. 什么是作用域?
- 二. `var a = 2`是如何赋值并添加到作用域中的?
- 三. 作用域链
- 四. js中的各种作用域
- 五. 闭包?
- 六. 参考
今天开始读了《你所不知道的JavaScript(上卷)》的一部分, 自己对于 JS 的理解还是非常浅薄的; 本着学习与分享的目的, 对这本书的第一章的内容进行理解与总结; 在浏览本文后, 如果发现有什么错误的地方,或者不到位的地方,欢迎指正!!!
一. 什么是作用域?
存储变量的值,并且之后可以对这个值进行访问或修改, 是几乎所有变成语言最基本的功能之一. 但是这些变量存在哪里, 如何快速找到他们, 这需要设计一套良好的规则来存储变量, 这套规则被称为作用域。(— 《你所不知道的JavaScript(上卷) 》)
在 MDN 对于js的作用域给出了这样的一个概念:
作用域是当前的执行上下文,在其中的值和表达式“可见”(可被访问)。如果一个变量或表达式不在当前的作用域中,那么它是不可用的。作用域也可以堆叠成层次结构,子作用域可以访问父作用域,反过来则不行。
简单来说: js 的作用域是变量或表达式的作用范围
二. var a = 2
是如何赋值并添加到作用域中的?
当我们编写了 var a = 2
这段程序是如何执行的呢? 又是怎么添加到作用域中的呢?
要理解这个问题, 先介绍一下js的三个好朋友
- 引擎: 负责整个js程序的编译及执行过程
- 编译器: 负责语法分析及代码生成
- 作用域: 负责收集并维护所有标识符(变量)组成的而查询,并实施一套非常严格的规则
当我们在运行var a = 2
这段程序, 会按照如下顺序去执行
- 编译器会将这段程序进行分词, 将词法单元解析成一个树状结构,
- 遇到
var a
, 编译器判断同一作用域集合中是否存在同名称的变量, 存在就会忽略该声明, 否则他会要求在作用域中声明一个新的命名为a的变量 - 编译器为引擎生成运行时的代码, 用来处理
a = 2
这个操作; - 引擎运行生成的代码, 现在同一作用域中去找名为a的变量, 如果存在就会使用这个变量, 如果没有找到就会在上一级作用域去寻找
- 引擎找到名为a的变量,将2赋值给他
三. 作用域链
作用域链是 JavaScript 中用于查找变量和函数的机制。它是由当前执行环境的一系列作用域对象组成的一个链式结构。
当在js中使用到一个变量时, 引擎会在当前作用域下去寻找该变量, 若没有找到, 就会到他的上层作用域去找, 若还没有找到会以此类推, 直到找到最外层作用域(全局作用域)为止;
如果在全局作用域里仍然找不到该变量,它就会在全局范围内隐式声明该变量(非严格模式下)或是直接报错
var a = 1function foo() {function bar() {console.log(a) // 1}bar()
}foo()
上段代码中使用到了a变量, 首先会在当前的作用域 (bar) 中找 a, 当前作用域中没有 a 变量, 再向上一级作用域( foo )中寻找, foo中的作用域也没有, 最后到全局作用域中找到了 a 变量;
四. js中的各种作用域
JavaScript 的作用域分以下几种:
- 全局作用域:脚本模式运行所有代码的默认作用域
全局作用域中的变量和函数可以在代码的任何位置被访问(只要在同一个 JavaScript 环境中)。
var a = 1;
console.log(a); // 1
- 模块作用域:模块模式中运行代码的作用域
模块可以包含变量、函数、类等各种定义,并且这些定义在模块外部是不可直接访问的,除非通过模块暴露的接口。这种作用域有助于防止命名冲突,同时也使得代码的组织更加清晰和模块化。
// 定义一个模块(myModule.js)
const myVariable = 10;
function myFunction() {console.log(myVariable);
}
export { myFunction };
- 函数作用域:由函数创建的作用域
函数内部定义的变量和函数具有函数作用域。这些变量和函数只能在函数内部被访问,外部无法直接访问函数内部的变量(除非通过闭包等特殊机制)。
function foo() {var a = 10;function bar() {var b = 20;console.log(a + b); // 30}bar();
}
foo();
console.log(a); // 会报错, a is not defined
- 块级作用域:用一对花括号(一个代码块)创建出来的作用域
使用let和catch语句块(try - catch结构中的catch块)等方式可以创建块级作用域。在一个块(由{}包围的代码区域)内部定义的变量,其作用域被限制在这个块内。
{let a = 10;console.log(a);
}
console.log(a); // 会报错,a is not defined
五. 闭包?
闭包是指有权访问另一个函数作用域中变量的函数。简单来说,当一个函数内部返回了一个新的函数,并且这个新函数可以访问到外部函数的变量,就形成了一个闭包。
闭包形成的条件
- 函数嵌套:必须有内部函数和外部函数的嵌套结构。外部函数定义了变量,内部函数能够访问这些变量。
- 内部函数被返回或传递到外部:内部函数需要以某种方式(如返回值、作为参数传递等)离开它原本的外部函数作用域,这样它才能在外部环境中被调用,并且依然能够访问外部函数中的变量。
function foo() {var a = 10;return function bar() {console.log(a);};
}
var baz = foo();
baz(); // 输出10, 没错这就是闭包
闭包的作用
- 数据隐藏和封装:闭包可以用于隐藏数据,外部无法直接访问内部函数所依赖的变量,只能通过返回的函数接口来操作。例如,在一个模块系统中,可以使用闭包来封装模块内部的状态变量,只暴露一些特定的方法来修改和获取这些变量的值。
- 函数式编程中的柯里化(Currying):闭包在函数式编程中用于实现柯里化。柯里化是把一个多参数的函数转换为一系列单参数的函数。
- 实现私有变量和方法:在 JavaScript 中没有像其他语言一样的私有成员访问修饰符,但是可以利用闭包来模拟私有变量和方法。
下面是使用闭包实现似有变量的例子:
var counter = (function() {var count = 0;return {increment: function() {count++;return count;},getCount: function() {return count;}};
})();
console.log(counter.increment()); // 输出1
console.log(counter.getCount()); // 输出1
闭包的潜在问题(内存泄漏)
由于闭包会使得内部函数引用外部函数的变量,在某些情况下,如果内部函数一直存在并且引用了外部函数中的大量变量,这些变量所占用的内存就无法被释放,从而导致内存泄漏。
例如,在浏览器的 DOM 事件处理中,如果一个闭包函数引用了一个包含大量数据的对象,并且这个闭包函数一直被添加到 DOM 元素的事件监听器中,那么这个对象就可能无法被垃圾回收,导致内存泄漏。解决这个问题通常需要在适当的时候移除事件监听器或者手动释放对闭包函数所引用对象的引用。
六. 参考
- mdn-作用域
- 《你所不知道的JavaScript(上卷)》
- 理解Javascript的作用域和作用域链
- 彻底弄懂JavaScript作用域问题
相关文章:
JavaScript的作用域与闭包
文章目录 一. 什么是作用域?二. var a 2是如何赋值并添加到作用域中的?三. 作用域链四. js中的各种作用域五. 闭包?六. 参考 今天开始读了《你所不知道的JavaScript(上卷)》的一部分, 自己对于 JS 的理解还是非常浅薄的; 本着学习与分享的目的, 对这本书的第一章的内容进行…...
Qt入门7——Qt事件
目录 1. Qt事件介绍: 2. 事件的处理 示例1:鼠标进入(enterEvent)与离开事件(leaveEvent) 示例2:鼠标点击事件(mousePressEvent) 示例3:鼠标移动事件(mouseMoveEvent) 3. 按键事件 4. 定时器 5. 窗口事件 1. Qt事件介绍&a…...
【Linux操作系统】多线程控制(创建,等待,终止、分离)
目录 一、线程与轻量级进程的关系二、进程创建1.线程创建线程创建函数(pthread)查看和理解线程id主线程与其他线程之间的关系 三、线程等待(回收)四、线程退出线程退出情况线程退出方法 五、线程分离线程的优点线程的缺点 一、线程…...
VR眼镜可视化编程:开启医疗信息系统新纪元
一、引言 随着科技的飞速发展,VR 可视化编程在医疗信息系统中的应用正逐渐成为医疗领域的新趋势。它不仅为医疗教育、手术培训、疼痛管理等方面带来了新的机遇,还在提升患者体验、推动医疗信息系统智能化等方面发挥着重要作用。 在当今医疗领域…...
数据结构自测题6
第7章 图 自测卷解答 一、单选题(每题1分,共16分) ( C )1. 在一个图中,所有顶点的度数之和等于图的边数的 倍。 A.1/2 B. 1 C. 2 D. 4 ( B )2. 在一个有向图中࿰…...
Marvell第四季度营收预计超预期,定制芯片需求激增
芯片制造商Marvell Technology(美满电子科技)(MRVL)在周二发布了强劲的业绩预告,预计第四季度的营收将超过市场预期,得益于企业对其定制人工智能芯片的需求激增。随着人工智能技术的快速发展,特…...
从智能合约到去中心化AI:Web3的技术蓝图
Web3正在成为互联网发展的重要方向,其核心理念是去中心化、用户主权和自治。随着区块链技术、智能合约以及人工智能(AI)等技术的发展,Web3不仅重新定义了数据存储和交易方式,还为更智能化、去中心化的数字生态系统铺平…...
opencvocr识别手机摄像头拍摄的指定区域文字,文字符合规则就语音报警
安装python,pycharm,自行安装。 Python下安装OpenCv 2.1 打开cmd,先安装opencv-python pip install opencv-python --user -i https://pypi.tuna.tsinghua.edu.cn/simple2.2 再安装opencv-contrib-python pip install opencv-contrib-python --user …...
python 笔记之线程同步和死锁
同步: 共享数据: 如果多个线程共同对某个数据修改,则可能出现不可预测的结果,为了保证数据的正确性,需要对多个数据进行同步 同步:一个一个的完成,一个做完另一个才能进来 效率会降低 使用Thre…...
解决Error resolving plugin xxx
问题信息 Error resolving plugin [id: com.android.library, version: 8.6.0] > The request for this plugin could not be satisfied because the plugin is already on the classpath with an unknown version, so compatibility cannot be checked.* Try: > Run wi…...
Word2vec、词向量是什么? |Gensim中word2vec模型的参数定义
前言: 最近在忙毕设,要学习一些AI的技术。很多资料看来看去,感觉只是在大脑皮层表面略过了一下,遂还是决定采用老方法,写博客!!!对了,我也只是一个萌新,博客的…...
<工具 Claude Desktop> 配置 MCP server 连接本地 SQLite, 本机文件夹(目录) 网络驱动器 Windows 11 系统
也是在学习中... 起因: 抖音博客 艾克AI分享 他的视频 #143《Claude开源MCP彻底打破AI的信息孤岛》 提到: Claude开源的MCP太强了,视频后面是快速演示,反正看了好几遍也没弄明白。菜单都不一样,感觉用的不是同一家 Claude. 探…...
Android10 设备死机的问题分析和解决
最近客户反馈一个问题,设备偶现死机。最后解决,在此记录。 目录 一死机的现象 二死机的类型 三 死机问题分析 1 死机现象的梳理 2 死机日志 1)日志分析一 2 日志分析二(正确方案) 一死机的现象 设备死机&#x…...
Linux操作系统性能优化
Linux操作系统性能优化 1. TCP连接出现大量ESTABLISHED连接解决方法 1. TCP连接出现大量ESTABLISHED连接解决方法 TCP协议规定,对于已经建立的连接,网络双方要进行四次握手才能成功断开连接,如果缺少了其中某个步骤,将会使连接处于…...
【图像处理】用Python和OpenCV实现简单的图像增强与特征提取
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 图像处理是计算机视觉领域的重要基础,而图像增强和特征提取是其中的关键技术。本文将详细探讨如何使用 Python 和 OpenCV 实现图像增强与特征提取。通过具体示例,我们将介绍滤波、直方图均衡化、边缘检测…...
【技术学习网站】
小黄鸭:面试鸭 - 程序员求职面试刷题神器,高频编程题目免费刷 编程导航:编程导航 - 程序员一站式编程学习交流社区,做您编程学习路上的导航员 博客园:博客园 - 开发者的网上家园 前端开发:HTTP 缓存 - H…...
程序员需要具备哪些知识?
程序员需要掌握的知识广泛而深厚,这主要取决于具体从事的领域和技术方向。不过,有些核心知识是共通的,就像建房子的地基一样,下面来讲讲这些关键领域: 1. 编程语言: 无论你是搞前端、后端、移动开发还是嵌…...
架构10-可观测性
零、文章目录 架构10-可观测性 1、可观测性 (1)可观测性的背景 **历史沿革:**可观测性最初由匈牙利数学家鲁道夫卡尔曼提出,用于线性动态控制系统。后来,该概念被引入到计算机科学中。**现代意义:**在分…...
Active RIS-Aided ISAC Systems: Beamforming Design and Performance Analysis
文章目录 II. SYSTEM MODELC. Active RIS Model III. PROBLEM FORMULATIONA. Radar Performance MetricC. Optimize Φ V. PERFORMANCE ANALYSIS OF THE RADAR SINR IN ACTIVE RIS-AIDED SENSING SYSTEMSA. Simplified System SettingB. Power Scaling Law AnalysisC. Active R…...
oracle 11g中如何快速设置表分区的自动增加
在很多业务系统中,一些大表一般通过分区表的形式来实现数据的分离管理,进而加快数据查询的速度。分区表运维管理的时候,由于人为操作容易忘记添加分区,导致业务数据写入报错。所以我们一般通过配置脚本或者利用oracle内置功能实现…...
HCIA-openGauss_1_4基本功能介绍
openGauss支持标准SQL SQL是用于访问和处理数据库的标准计算机语言,SQL标准的定义分成核心特性以及可选特性,绝大部分的数据库都没有100%支撑SQL标准。openGuass支持SQL2003标准语法,支持主备部署的高性能可用关系型数据库。openGauss数据库…...
el-menu导航三级数据结构及数据展示
1:数据展示 <el-col><el-menu:default-active"$route.path"class"el-menu-vertical-demo"routerunique-openedbackground-color"#545c64"text-color"#fff"active-text-color"#ffd04b"><div v-for"item …...
全面解析 Transformer:改变深度学习格局的神经网络架构
目录 一、什么是 Transformer? 二、Transformer 的结构解析 1. 编码器(Encoder) 2. 解码器(Decoder) 3. Transformer 模型结构图 三、核心技术:注意力机制与多头注意力 1. 注意力机制 2. 多头注意力&…...
R语言机器学习论文(二):数据准备
禁止商业或二改转载,仅供自学使用,侵权必究,如需截取部分内容请后台联系作者! 文章目录 介绍加载R包数据下载导入数据一、数据描述二、数据预处理(一)修改元素名称(二)剔除无关变量(三)缺失值检查(四)重复值检查(五)异常值检查三、描述性统计(一)连续变量数据情…...
Linux之socket编程(一)
前言 网络通信的目的 我们已经大致了解了网络通信的过程: 如果主机A想发送数据给主机B, 就需要不断地对本层的协议数据单元(PDU)封装, 然后经过交换设备的转发发送给目的主机, 最终解封装获取数据. 那么网络传输的意义只是将数据由一台主机发送到另一台主机吗? …...
STM32之SDIO通讯接口和SD卡(九)
STM32F407 系列文章 - SDIO-To-SD Card(九) 目录 前言 一、SDIO接口 二、SD卡 三、实现程序 1.SD卡结构体参数说明 2.头文件定义 3.函数sd_init() 4.函数HAL_SD_MspInit() 5.函数get_sd_card_info() 6.函数get_sd_card_state() 7.函数sd_read…...
【Rust在WASM中实现pdf文件的生成】
Rust在WASM中实现pdf文件的生成 前言概念和依赖问题描述分步实现pdf转Blob生成URL两种方式利用localstorage传递参数处理图片Vec<u8>到pdf格式的Vec<u8>使用rust创建iframe显示pdf的Blob最后 前言 实现了一个通用的前端jpg转pdf的wasm,因为动态响应框架无法直接打…...
蓝桥杯真题——砍竹子(C语言)
问题描述 这天, 小明在砍竹子, 他面前有 n 棵竹子排成一排, 一开始第 ii 棵竹子的 高度为 .他觉得一棵一棵砍太慢了, 决定使用魔法来砍竹子。魔法可以对连续的一 段相同高度的竹子使用, 假设这一段竹子的高度为 H, 那么用一次魔法可以,把这一段竹子的高度都变为, 其中 [x]表…...
技术栈4:Docker入门 Linux入门指令
目录 1.Linux系统目录结构 2.处理目录的常用命令 3.Docker概述 4.Docker历史 5.Docker基本组成 6.Docker底层原理 7.Docker修改镜像源 8.Docker基本命令 在学习docker之前我们先要熟悉Linux系统,推荐阅读:Linux笔记(狂神说࿰…...
项目开发之Docker
文章目录 基础核心概念常用命令 实操1 windows11 docker mysql2 docker部署 xxljob3 container间调用异常问题4 部署mysql数据库5 docker desktop unexpected wsl error 基础 核心概念 其中的三个核心概念:dockerfile image/镜像 container/容器 image:…...
状态模式的理解和实践
在软件开发中,我们经常遇到需要根据对象的不同状态执行不同行为的情况。如果直接将这些状态判断和行为逻辑写在同一个类中,会导致该类变得臃肿且难以维护。为了解决这个问题,状态模式(State Pattern)应运而生。状态模式…...
正点原子imx6ull配置MQTT客户端上传数据到Ubuntu MQTT服务器
目录 使用QT自带的MQTT模块部署客户端创建一个class专门用于MQTT客户端通讯使用QT在ui界面上生成按钮在Windows上订阅相应主题测试在imx6ull上订阅Windows发布的消息 在上一篇中介绍了在Ubuntu22.04的Docker中部署MQTT服务器,然后在window上测试订阅和发布ÿ…...
【联表查询】.NET开源 ORM 框架 SqlSugar 系列
.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...
CAN接口设计
CAN总线的拓扑结构 CAN总线的拓扑结构有点像485总线,都是差分的传输方式,总线上都可以支持多个设备,端接匹配电阻都是120Ω。 485和CAN通信方面最大的区别:网络特性。485是一主多从的通讯方式,CAN是多主通讯,多个设备都可以做主机。那多个设备都相要控制总线呢?…...
基于遗传优化SVM的电机参数预测matlab仿真
目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1 数据收集与预处理 4.2模型构建与训练 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 输入:电机结构参数x1 x2 x3 x4 x5(分别是铁心高度 铁心厚度 绕组…...
C++设计模式之代理模式
动机 在面向对象系统中,有些对象由于某种原因(比如对象创建的开销很大,或者某些操作需要安全控制,或者需要进程外的访问等),直接访问会给使用者、或者系统结构带来很多麻烦。 如何在不失去透明操作对象的…...
多线程JUC 第2季 控制线程的执行顺序,依次,交替,同时
一 场景1 交替执行 1.1 方案1使用completablefuture public class TestA {public static void main(String[] args) {for(int k0;k<10;k) {CompletableFuture<Void> t1 CompletableFuture.runAsync(() -> {System.out.println("A: >" Thread.curr…...
数据分析(一): 掌握STDF 掌握金钥匙-码农切入半导体的捷径
中国的半导体行业必然崛起!看清这个大势,就会有很多机会。 今天,我们一起来了解一下半导体行业的一朵金花:STDF。 实际上这只是一种文件格式,但是当你熟练掌握解析这种文件的时候,你就已经打开在这个基础…...
NPM镜像详解
NPM镜像详解 什么是NPM镜像 NPM镜像(NPM Mirror)是一个完整的NPM包的副本服务器。由于npm的官方registry服务器部署在国外,国内访问可能会比较慢,因此使用镜像可以加快包的下载速度。 常用的NPM镜像源 npm官方镜像 https://reg…...
【springboot】 多数据源实现
文章目录 1. 引言:多数据源的必要性和应用场景**为什么需要多数据源?****应用场景** 2. Spring Boot中的数据源配置2.1 默认数据源配置简介2.2 如何在Spring Boot中配置多个数据源 3. 整合MyBatis与多数据源**配置MyBatis使用多数据源****Mapper接口的数…...
Zephyr 入门-设备树与设备驱动模型
学习链接:https://www.bilibili.com/video/BV1L94y1F7qS/?spm_id_from333.337.search-card.all.click&vd_source031c58084cf824f3b16987292f60ed3c 讲解清晰,逻辑清楚。 1. 设备树概述(语法,如何配置硬件,c代码如…...
css实现圆周运动效果
在CSS中可以通过 keyframes 动画 和 transform 属性实现元素的圆周运动。以下是一个示例代码: 示例代码 <!DOCTYPE html> <html lang"en"> <head> <meta charset"UTF-8"> <meta name"viewport" content…...
乐鑫科技嵌入式面试题及参考答案(3万字长文)
嵌入式开发为什么用 C 语言,而不用 C++ 语言? 在嵌入式开发中,C 语言被广泛使用而 C++ 相对少用有以下一些原因。 首先,C 语言具有更高的效率。嵌入式系统通常资源受限,包括处理器速度、内存容量等。C 语言的代码生成效率高,能够生成紧凑的机器码,占用较少的内存空间和处…...
这就是IoC容器
IoC(Inversion of Control,控制反转),也叫依赖注入(Dependency Injection),是一种决定容器如何装配组件的模式。使用 Spring 来实现 IoC,意味着将设计好的对象交给 Spring 容器控制,而不是直接在对象内部控制。控制反转不能很好地描述这个模式,依赖注入却能更好地描述…...
KVM OVS双网卡配置trunk模式
一、宿主机配置 1. 确保必要的软件包已安装 确保宿主机上已安装 Open vSwitch 和 VLAN 工具。如果尚未安装,可以使用以下命令进行安装: yum install openvswitch-switch vlan 2. 配置现有 OVS 桥接 br0 假设已有一个 OVS 桥接接口 br0,并…...
氢能源车和电动车,谁将成为未来?
很多人都觉得氢能源是未来的终极绿色能源,因为氢气燃烧后只产生水,听起来是不是很环保?但这只是从化学能的角度来看。实际上,氢能源汽车还有很多问题需要解决。氢气的制作成本高得吓人 目前,制作氢气最理想的方法是电…...
CTF-PWN: WEB_and_PWN [第一届“吾杯”网络安全技能大赛 Calculator] 赛后学习(不会)
附件 calculate.html <!DOCTYPE html> <html lang"en"> <head><!-- 设置字符编码为 UTF-8,支持多语言字符集 --><meta charset"UTF-8"><!-- 设置响应式视图,确保页面在不同设备上自适应显示 --&…...
解决Jupyter Notebook无法转化为Pdf的问题(基于Typora非常实用)
笔者在完成各项作业和做笔记时,经常用到jupyter notebook;其因为可以同时运行python并提供格式化的数字公式的输入方式,得到了广大用户的喜爱。 当我们想要将.ipynb文件导出为pdf时,有两种常用方法。 1.Ctrlp 2.通过File ->…...
矩阵转置
矩阵转置 C语言代码C 语言代码Java语言代码Python语言代码 💐The Begin💐点点关注,收藏不迷路💐 输入一个n行m列的矩阵A,输出它的转置 A T A^T AT。 输入 第一行包含两个整数n和m,表示矩阵A的行数和列数。…...
【阅读笔记】Three ways ChatGPT helps me in my academic writing
Three ways ChatGPT helps me in my academic writing 论文地址 关于GPT进行润色的文章,摘取了里面的提示词做个记录。 1. Polishing academic writing(学术润色) 模板:I’m writing a paper on [topic] for a leading [discip…...