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

js的作用域,作用域链,执行上下文,变量对象,活动对象

1、什么是作用域?作用域链?

作用域是个很抽象的概念,他是javaScript代码中变量和函数可访问的环境。他决定了哪些代码能访问某些变量或者属性。

作用域分为:全局作用域,函数作用域,块级作用域

作用域链决定了变量的查找顺序和查找范围。

let a='123'function inner(){console.log(a)}function outer(){let a='456'inner()}outer() //123

 以上代码共有三个作用域:其中一个全局作用域,两个函数作用域。

两个函数的变量对象分别对应一条作用域链

inner变量对象-》全局变量对象

outer变量对象-》全局变量对象

所以,inner函数执行的时候,沿着作用域链找到了全局变量对象(代码执行的时候全局变量对象其实已经是活动对象了)的a变量,因此输出‘123’

2、什么是执行上下文?执行上下文栈?

执行上下文指的是一种执行环境,执行上下文栈是一种存储执行上下文的栈结构。当js脚本开始执行的时候,首先会将全局的执行上下文推入栈中,如果在全局执行上下文中调用了某个函数,则会创建一个函数执行上下文,并推入栈中,函数执行上下文执行完毕后会弹出栈,继续全局执行上下文的执行。

总之,执行上下文栈中栈顶永远是当前正在执行的上下文环境,栈底永远是全局执行上下文。

3、变量对象和活动对象是什么?

每一个执行上下文环境都会对应一个变量对象,用于存储该上下文环境中的变量和函数。比如,函数一经调用,函数的执行上下文就被推入栈中,在函数体代码正式执行之前,该执行上下文的变量对象会进行创建。

function(num1,num2){let result=num1+num2console.log(result)
}

比如这个函数,上下文对应的变量对象就有num1,num2,result,arguments这些变量,可供函数体中的代码进行访问。

活动对象是变量对象其实是一个对象,当函数体开始执行的时候,变量对象中的变量就会被初始化并赋值,这时候变量对象就变成了活动对象。

4、作用域链增强

两种方式:with语句块,catch块

with语句块:

function test(){let a='qwe'with(location){let b=href+a;}return b;}console.log(test())

如上,test函数调用的时候,首先是创建一个函数作用域和函数的执行上下文,在该上下文中声明了变量a。执行到with语句时,在作用域链的前端又新加了一个以location为变量对象的上下文。在with语句块中声明的变量b,只在新的上下文中可访问。with语句执行完毕后,b就会被销毁。因此在函数test的执行上下文中访问b会报错。

想要在函数作用域中能够访问到内部块级作用域中的变量,则变量应该用var去声明,因为var声明的变量会挂到最近的函数执行上下文,而let声明的变量只会挂到最近的块级执行上下文。如下:

function test(){let a='qwe'with(location){var b=href+a;}return b;}console.log(test())

with使访问变量更加方便,location.href可以直接写成href。但是带来了很大的性能开销,因此在严格模式下禁用。

catch块:

function createErrorLogger() {let errorCount = 0; // 外部作用域变量return function (error) {try {throw error;} catch (e) {errorCount++; // 修改外部作用域变量(通过闭包)console.log(`Error ${errorCount}:`, e.message);console.log("Accessing outer var:", errorCount); // 可访问外部变量}// console.log(e); // 仍无法在外部访问 e};
}

如上代码:catch 块通过词法环境动态绑定异常对象到标识符 ee 仅在 catch 块内有效,且必须显式通过 e 访问(类似函数参数的传递)。

with和catch对比:

特性with 语句catch 块
作用域处理方式动态修改作用域链(运行时调整)动态创建词法环境(编译时绑定)
对象绑定方式将外部对象临时插入作用域链顶部将异常对象绑定到标识符 e
属性访问可省略对象名(直接访问属性)必须显式通过 e 访问异常对象属性
作用域范围仅限 with 块内仅限 catch 块内
是否创建新变量对象否(仅修改作用域链)否(动态绑定到词法环境)
引擎实现方式运行时动态调整作用域链编译时生成词法环境结构
http://www.xdnf.cn/news/149689.html

相关文章:

  • 谷歌AI眼镜:你的第二大脑,未来人机共生从这里开始
  • 前端如何获取文件的 Hash 值?多种方式详解、对比与实践指南
  • 列表与字典应用
  • 动态规划算法详解(C++)
  • EFL格式|动态库加载 | 重谈地址空间(2)
  • 复合材料高置信度 DIC 测量与高级实验技术研讨会邀请函
  • 达梦数据库压力测试报错超出全局hash join空间,适当增加HJ_BUF_GLOBAL_SIZE解决
  • 【计算机视觉】CV实战项目 - 基于YOLOv5的人脸检测与关键点定位系统深度解析
  • mysql 安装
  • 项目实战-基于大数据分析的暖通系统改造模型【感谢Akila公司以及学院的支持】
  • Lobechat使用WolframAlpha MCP工具减少LLM幻觉
  • Java 设计模式心法之第23篇 - 状态 (State) - 让对象的行为随状态优雅切换
  • 【蓝桥杯选拔赛真题104】Scratch回文数 第十五届蓝桥杯scratch图形化编程 少儿编程创意编程选拔赛真题解析
  • IPOF(Input-Process-Output-Feedback)方法学简介
  • XMOS空间音频——在任何设备上都能提供3D沉浸式空间音频且实现更安全地聆听
  • 【计算机视觉】CV实践项目- 基于PaddleSeg的遥感建筑变化检测全解析:从U-Net 3+原理到工程实践
  • numpy.random.normal与numpy.random.randn的区别与联系
  • 雷电模拟器怎么更改IP地址
  • 使用 Python 项目管理工具 uv 快速创建 MCP 服务(Cherry Studio、Trae 添加 MCP 服务)
  • Jetpack Compose 基础组件学习2.1:Surface
  • stack __ queue(栈和队列)
  • 分布式事务 两阶段提交协议(2PC的原理、挑战)
  • 大模型微调 - 自注意力机制
  • 【统计学习】递归最小二乘算法与奇异值分解
  • #什么是爬虫?——从技术原理到现实应用的全面解析 VI
  • Vue回调函数中的this
  • 【CF】Day43——Codeforces Round 906 (Div. 2) E1
  • Libconfig 修改配置文件里的某个节点
  • Linux 系统用户管理与权限掌控:从基础到精通
  • 《深入理解计算机系统》阅读笔记之第三章 程序的机器级表示