当前位置: 首页 > news >正文

Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链。函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境。全局执行环境只能访问全局执行环境的变量和函数,不能直接访问局部环境中的信息;变量的执行环境有助于确定何时应该释放内存。离开作用域的值会被标记为可以回收,将在垃圾收集期间被删除。javascript中有“标记清楚” 和 “引用计数” 两种垃圾收集算法。

  执行环境 (execution context)

  执行环境是javascript中很重要的一个概念。变量或函数的 execution context 定义它们有权访问的其它数据,以及变量或函数各自的行为。每个执行环境都有一个与之关联的 变量对象(variable object) ,环境中定义的所有变量和函数都保存在这个对象中。我们编写的代码无法访问到这个对象,但是解析器在处理数据时会在后台使用它。

  全局执行环境是最外围的一个执行环境,根据 ECMAScript 实现坐在的宿主环境的不同,表示执行环境的对象也不同。浏览器中,全局执行环境被认为是window对象,所有的全局变量和函数都作为window对象的属性或方法存在。

 某个执行环境中的代码一旦执行完毕,该环境会被销毁,保存在其中的变量、函数都将随之销毁。每个函数都有一个自己的执行环境。全局执行环境会直到应用程序退出才会被销毁,比如关闭网页。

  作用域链 (scope chain)

  当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的作用是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链可以看作是一个个变量对象的有机、有序连接,作用域链的第一个对象,始终都是当前执行的代码所在环境的 变量对象。作用域链的下一个对象来自其外部环境,而在下一个对象则来自下一个外部环境,这样一直延续到全局执行环境。作用域链的最后一个对象始终都是全局执行环境的变量对象对象。如果执行环境是一个函数,则将其活动对象(activation object)作为变量对象。活动对象在最开始只包含一个变量,即arguments对象(全局环境中不存在该对象)。

  标识符的解析就是沿着作用域链一级一级的搜索标识符的过程,知道找到标识符,如果标识符未被找到则会导致错误发生。如下所示:

var name = "Zhang San";function changeName()
{var newName = "Li Si";function execute(){var tempName = newName;newName = name;name = tempName;// 可以访问 name / newName / tempName}execute();// 可以访问 name / newName , 不能访问 tempName
}
changeName();
// 只能访问 name

 示例涉及3个执行环境:全局环境、changeName()的局部环境和 execute() 的局部环境。内部环境可以通过作用域链访问所有的外部环境,但是外部环境不能访问内部环境中的任何变量和函数。这些环境之间的联系是线性、有序的。每个环境都可以向上搜索作用域,以查询变量和函数名;但都不能向下搜索作用域链而进入另一个执行环境。

  作用域链延长

  尽管执行环境总共有全局执行环境和局部执行环境(函数)两种,但还是有一些语句会使作用域链的前段临时增加一个变量对象,改变量对象会在代码执行后被移除。两种情况下会发生这种现象,当执行流进入下列任一语句时,作用域链就会得到加长:

  1. catch块
  2. with语句

  没有块级作用域

  javascript 没有块级作用域。在其他类 C 的语言中,由大括号封闭的代码都有自己的作用域,可以实现自根据条件来定义变量。

if(true){var name = "Zhang San";
}
alert(name);    // "Zhan San"

如上例所示,变量 name 被添加到了当前的执行环境(即全局环境)中,如果在 C/C++/JAVA 的语言中变量 name 则会在if语句执行完毕后被销毁。下面在看一个例子:

for(var i = 0; i < 10; i++){// code ...
}
alert(i);     //

上例中,变量 i 并没有随着循环的结束而被销毁,而是被定义在了当前执行环境(全局环境)中,这一点要尤为注意。

  声明变量

  使用 var 关键字声明的变量会被自动添加到最接近的执行环境中,如果在函数内部,最接近的执行环境就是函数的局部环境;在with语句中,最接近的环境是函数环境。如果没有使用 var 关键字定义变量,那么该变量会被添加到全局环境中。  

function getName(){var Name = "Zhang San";globalName = "Li Si";return Name;
}
getName(); // "Zhang San"
alert(globalName);    // "Li Si"

标识符查询

  当在某个环境中为了读取或写入而引用一个标识符时,必须通过搜索来确定该标识符的值。搜索过程从作用域链的最前端开始逐级向上查找,直到匹配到变量名。在这条链路上一旦找到标识符则查询工作立即结束,变量就绪。搜索过程会一直追溯到全局环境,如果在全局环境中仍未匹配到改查询则说明变量为声明。

  垃圾回收

  javascript 具备垃圾回收机制,执行环节会负责管理代码执行过程中使用的内存。开发人员几乎不必去关注内存使用问题,分不配和回收内存完全实现了自动管理。垃圾回收机制的原理是:找出那些不再继续使用的变量,然后释放其占用的内存。垃圾收集器会按固定的时间间隔周期性的执行这一操作。

  函数中局部变量的生命周期:局部变量只在函数执行过程中存在,在这个过程中会为局部变量分配内存以存储他们的值,然后函数中使用这些变量进行一系列操作。当函数执行完毕,这些局部变量也就没有存在的价值了,可以释放他们的内存一共将来使用。

  垃圾收集器必须跟踪变量的状态,以确定它们是否已经不会再被使用,对于不再使用的变量打上标记,以备将来收回其占用的内存。如此一来,标识无用变量的策略就显得尤为重要,具体到浏览器中,通常有两种策略。

  1. 标记清除(Mark-and-Sweep)

  最常用的垃圾收集策略就是标记清除,当一个变量进入执行环境(context),例如在函数中生命了一个变量,则这个变量会被标记为进入执行环境( begin in context),理论上标记为进入环境的变量是不能被回收的。当变量离开执行环境,则将其标记为离开环境(out of context)。

  当垃圾收集器运行时,会为所有存储在内存中的变量加上标记,然后取消 在当前执行环境中的变量和被当前执行环境中变量引用的变量 的标记。现在,所有被加上标记的变量都被认为是可以删除的变量,接着,垃圾收集器会便开始了他的内存清除工作,收回那些无效变量占用的内存。

  不同浏览器都实用类类似的垃圾收集策略,只不过垃圾收集器运行的时间间隔不同。

  2. 引用计数(reference counting)

  另一种垃圾收集机制是引用计数,这种策会跟踪记录每个值被引用的次数,当声明一个变量并赋值一个引用类型值时,这个值的引用次数就加会1。如果,包含对这个值的引用被取消,或者该变量有被赋值为其它值,则这个引用类型的值的引用次数就会减1。如果这个引用类型的值的引用次数为0,那么它将被垃圾回收机制回收。

  这种回收策略有一个限制,就是当代码中存在循环引用时,相关对象的引用计数就永远不会为0,对象也就无法被回收。除非开发人员,明确的为相关对象解除引用。

相关文章:

Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

执行环境有全局执行环境和函数执行环境之分&#xff0c;每次进入一个新执行环境&#xff0c;都会创建一个搜索变量和函数的作用域链。函数的局部环境不仅有权访问函数作用于中的变量&#xff0c;而且可以访问其外部环境&#xff0c;直到全局环境。全局执行环境只能访问全局执行…...

CRDT协同算法

CRDT的英文全称是Conflict-free Replicated Data Type&#xff0c;最初是由协同文本编辑和移动计算而发展的&#xff0c;现在还被用作在线聊天系统、音频分发平台等等。当前CRDT算法在富文本编辑器领域的协同依旧是典型的场景&#xff0c;常用于作为实现文档协同的底层算法&…...

近代中国的三次思想文化运动

1、戊戌变法中维新派顽固派论战 第一次思想解放潮流是1898年维新派与顽固势力的论战。论战的内容有&#xff1a;要不要变法&#xff0c;要不要兴民权、实行君主立宪&#xff0c;要不要提倡西学、改变教育制度。此次论争是资本主义思想同封建主义思想的正面交锋&#xff0c;此后…...

《地铁上的面试题》--目录

第一部分&#xff1a;基础 数据结构与算法 1.1 数组和链表 1.2 栈和队列 1.3 树和图 1.4 排序和搜索算法 1.5 动态规划和贪心算法 操作系统 2.1 进程与线程 2.2 内存管理 2.3 文件系统 2.4 进程同步与通信 2.5 虚拟化和容器化技术 计算机网络 3.1 TCP/IP协议 3.2 HTTP和HTTPS…...

在VIVADO下烧写ZC706板载FLASH的操作步骤

1&#xff0c;原理图分析 首先看原理图&#xff0c;我们兼容ZC706的板子有两片 FLASH&#xff0c;型号是S25FL128A,连接方式如下&#xff1a; 可以看到两片是分别接在了XC7Z045芯片的引脚上&#xff0c;是互不相干的并联方式&#xff0c;每个FLASH芯片支持X4模式&#xff0c;也…...

第二期:链表经典例题(两数相加,删除链表倒数第N个节点,合并两个有序列表)

每道题后都有解析帮助你分析做题&#xff0c;答案在最下面&#xff0c;关注博主每天持续更新。 PS&#xff1a;每道题解题方法不唯一&#xff0c;欢迎讨论&#xff01; 1.两数相加 题目描述 给你两个非空的链表&#xff0c;表示两个非负的整数。它们每位数字都是按照逆序的方式…...

ESP32设备驱动-SHT35湿度传感器驱动

SHT35湿度传感器驱动 1、SHT35介绍 SHT35 数字温湿度传感器基于 Sensirion SHT35 传感器 IC。 得益于Sensirion的CMOSens技术,高度集成的电容式湿度传感元件和带隙温度传感元件,SHT35具有高可靠性和长期稳定性,功耗低,响应速度快,抗干扰能力强。 传感器支持IIC通信,兼容…...

如何快速判断GitLab 是否出现 OOM

查看系统日志&#xff1a; 使用 dmesg 命令来查看系统日志&#xff0c;搜索 Out of memory 关键字&#xff1a; sudo dmesg | grep -i "out of memory"如果输出结果中包含 Out of memory 或 oom-killer 等关键字&#xff0c;则表示系统出现了 OOM。 查看 GitLab 日…...

Word查找和替换通配符(完全版)

Word查找栏代码通配符一览表 序号 清除使用通配符复选框 勾选使用通配符复选框 特殊字符 代码 特殊字符 代码or通配符 1 任意单个字符 ^? 任意单个字符 ? 2 任意数字 ^# 任意数字&#xff08;单个&#xff09; [0-9] 3 任意英文字母 ^$ 任意英文字母 [a…...

Linux下socketpair系统API调用使用说明

目录 1.socketpair函数说明 2.socketpair使用举例 在阅读nginx源码时&#xff0c;发现其调用socketpair来实现master和worker进程之间进行数据交互。其代码如下&#xff1a; 思考&#xff1a;master和worker进程是父子关系&#xff0c;有亲属关系的进程通过pipe/pipe2&#x…...

【Netty】Future 源码分析(十六)

文章目录 前言一、JDK 的 Future 接口二、Netty 的 Future 接口三、ChannelFuture 接口总结 前言 回顾Netty系列文章&#xff1a; Netty 概述&#xff08;一&#xff09;Netty 架构设计&#xff08;二&#xff09;Netty Channel 概述&#xff08;三&#xff09;Netty Channel…...

5月《中国数据库行业分析报告》正式发布,首发时序、实时数据库两大【全球产业图谱】

为了帮助大家及时了解中国数据库行业发展现状、梳理当前数据库市场环境和产品生态等情况&#xff0c;从2022年4月起&#xff0c;墨天轮社区行业分析研究团队出品将持续每月为大家推出最新《中国数据库行业分析报告》&#xff0c;持续传播数据技术知识、努力促进技术创新与行业生…...

【计算机视觉 | 目标检测】术语理解6:ViT 变种( ViT-H、ViT-L ViT-B)、bbox(边界框)、边界框的绘制(含源代码)

文章目录 一、ViT & ViT变种1.1 ViT的介绍1.2 ViT 的变种 二、bbox&#xff08;边界框&#xff09;三、边界框的绘制 一、ViT & ViT变种 1.1 ViT的介绍 ViT&#xff0c;全称为Vision Transformer&#xff0c;是一种基于Transformer架构的视觉处理模型。传统的计算机视…...

为kong网关添加限流插件

限流用于控制发送到上游服务的请求速率。 它可用于防止 DoS 攻击、限制网络抓取和其他形式的过度使用。 如果没有速率限制&#xff0c;客户可以无限制地访问您的上游服务&#xff0c;这可能会对可用性产生负面影响。 一、全局范围内的限流 1、启用限流 [rootmin ~]# curl -i…...

Python接口自动化—接口测试用例和接口测试报告模板

简介 当今社会在测试领域&#xff0c;接口测试已经越来越多的被提及&#xff0c;被重视&#xff0c;而且现在好多招聘信息要对接口测试提出要求。区别于传统意义上的系统级别测试&#xff0c;很多测试人员在接触到接口测试的时候&#xff0c;也许对测试执行还可以比较顺利的上…...

C++无锁队列

C无锁队列是一种多线程编程技术&#xff0c;它可以在不使用锁的情况下实现线程安全的队列。它可以提高多线程程序的性能。 无锁队列的主要思想是让多个线程同时访问队列&#xff0c;而不需要使用锁来保护共享资源。这可以避免锁竞争和死锁等问题&#xff0c;从而提高程序的效率…...

MySQL 5.7 修改账号密码

MySQL 5.7 修改账号密码 1、概述2、更改密码2.1、寻找命令2.2、补充 3、总结 1、概述 大家好&#xff0c;我是欧阳方超。 MySQL数据库安装后设置的密码太简单了&#xff0c; 近期安全检查&#xff0c;这种弱密码全部得修改&#xff0c;好吧那就开始改吧 2、更改密码 2.1、寻…...

ARM实验6-基于中断的按键处理程序实验

一、实验名称:基于中断的按键处理程序实验 二、实验目的: 1.掌握ARM处理器的中断处理过程。 2.掌握ARM处理器中断服务程序的编写方法。 3.通过该编程实验,进一步巩固和强化学生ARM汇编编程的能,ARM应用程序框架,培养学生实际应用的能力。 三、实验内容: 按下面电路图,…...

安全认证:

1. 认证概述 为什么要有认证&#xff1f; 防止非法路由器接入企业内网的ospf路由器&#xff0c;保护内网安全 2. 认证方式 认证方式分为接口认证和区域认证&#xff0c;接口认证和区域认证没有本质的区别&#xff0c;接口认证是当区域内链路过多的情况下&#xff0c;接口认证…...

C++11新特性:decltype类型推导

上一节所讲的 auto&#xff0c;用于通过一个表达式在编译时确定待定义的变量类型&#xff0c;auto 所修饰的变量必须被初始化&#xff0c;编译器需要通过初始化来确定 auto 所代表的类型&#xff0c;即必须要定义变量。若仅希望得到类型&#xff0c;而不需要(或不能)定义变量的…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

鱼香ros docker配置镜像报错:https://registry-1.docker.io/v2/

使用鱼香ros一件安装docker时的https://registry-1.docker.io/v2/问题 一键安装指令 wget http://fishros.com/install -O fishros && . fishros出现问题&#xff1a;docker pull 失败 网络不同&#xff0c;需要使用镜像源 按照如下步骤操作 sudo vi /etc/docker/dae…...

重启Eureka集群中的节点,对已经注册的服务有什么影响

先看答案&#xff0c;如果正确地操作&#xff0c;重启Eureka集群中的节点&#xff0c;对已经注册的服务影响非常小&#xff0c;甚至可以做到无感知。 但如果操作不当&#xff0c;可能会引发短暂的服务发现问题。 下面我们从Eureka的核心工作原理来详细分析这个问题。 Eureka的…...

SiFli 52把Imagie图片,Font字体资源放在指定位置,编译成指定img.bin和font.bin的问题

分区配置 (ptab.json) img 属性介绍&#xff1a; img 属性指定分区存放的 image 名称&#xff0c;指定的 image 名称必须是当前工程生成的 binary 。 如果 binary 有多个文件&#xff0c;则以 proj_name:binary_name 格式指定文件名&#xff0c; proj_name 为工程 名&…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

CSS | transition 和 transform的用处和区别

省流总结&#xff1a; transform用于变换/变形&#xff0c;transition是动画控制器 transform 用来对元素进行变形&#xff0c;常见的操作如下&#xff0c;它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

第7篇:中间件全链路监控与 SQL 性能分析实践

7.1 章节导读 在构建数据库中间件的过程中&#xff0c;可观测性 和 性能分析 是保障系统稳定性与可维护性的核心能力。 特别是在复杂分布式场景中&#xff0c;必须做到&#xff1a; &#x1f50d; 追踪每一条 SQL 的生命周期&#xff08;从入口到数据库执行&#xff09;&#…...

Python网页自动化Selenium中文文档

1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API&#xff0c;让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API&#xff0c;你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

从零手写Java版本的LSM Tree (一):LSM Tree 概述

&#x1f525; 推荐一个高质量的Java LSM Tree开源项目&#xff01; https://github.com/brianxiadong/java-lsm-tree java-lsm-tree 是一个从零实现的Log-Structured Merge Tree&#xff0c;专为高并发写入场景设计。 核心亮点&#xff1a; ⚡ 极致性能&#xff1a;写入速度超…...