如何理解JavaScript中的词法作用域_JavaScript作用域链如何查找变量

云晨姑娘_9874

云晨姑娘_9874

2026-01-10

766人浏览

原创

词法作用域在函数定义时就确定了,变量可访问性取决于代码书写位置而非调用位置;作用域链在函数创建时固化于[[Environment]]中,沿词法嵌套逐级向上查找,与调用栈无关。

如何理解javascript中的词法作用域_javascript作用域链如何查找变量

词法作用域在函数定义时就确定了,不是调用时

JavaScript 的词法作用域(Lexical Scope)意味着变量的可访问性取决于函数在代码中**书写的位置**,而不是它在哪里被调用。这和动态作用域完全不同——你不需要运行代码就能大致判断某个 var、let 或 const 是否能被访问。

比如嵌套函数中引用外层变量,只要外层变量在语法上“包围”了内层函数,就构成词法闭包。即使外层函数已经执行完毕,只要内层函数还存在(比如被返回或赋值给变量),它依然能访问那些变量。

  • function outer() { const x = 10; return function inner() { console.log(x); }; } —— inner 能访问 x,因为定义时就在 outer 函数体内
  • const fn = outer(); fn(); —— 此时 outer 已执行结束,但 fn 仍持有对 x 的引用
  • 如果把 inner 拿到全局去调用,它依然找的是定义时的外层作用域,不是调用时的全局作用域

作用域链是静态构建的查找路径,从当前作用域逐级向上

当 JS 引擎查找一个变量(比如 console.log(a) 中的 a),它不会跳着找,而是沿着一条预先确定的链路:先查当前执行上下文的词法环境(Local),没找到就查外层词法环境(Outer),再没找到就继续往上,直到全局对象(浏览器是 window,Node 是 globalThis)。这条链就是作用域链。

这个链在函数创建时就固化在函数的 [[Environment]] 内部槽里,跟调用栈无关。哪怕函数被传到别的模块或作为回调执行,它的作用域链也不会变。

  • 每个函数都有自己的 [[Environment]],指向其定义时的词法环境
  • 全局代码的作用域链只有一层:全局环境
  • eval() 有特殊规则,会临时插入当前作用域,但日常应避免使用
  • 箭头函数没有自己的 this 和 arguments,但它同样遵循词法作用域——它的 [[Environment]] 指向定义时的外层函数环境

let/const 块级作用域会影响作用域链的“起点”

let 和 const 声明的变量绑定在块级词法环境中(比如 if、for、{}),而 var 只绑定在函数级或全局级。这意味着作用域链的“最底层”可能是一个块环境,而不只是函数环境。

javascript-typescript-typescript-scaffold
javascript-typescript-typescript-scaffold

你是 TypeScript 项目架构专家,专注于脚手架搭建生产就绪的 Node.js 和前端应用。生成包含现代工具链(pnpm、Vite、Next.js)、类型

下载

不过要注意:块级环境本身不创建新的作用域链,它只是函数作用域内部的一个“子环境”。JS 引擎在查找变量时,会先检查当前块,再退回到所在函数,再往上。

function foo() {
  if (true) {
    let x = 1;
    var y = 2;
  }
  console.log(y); // ✅ 可以访问,y 提升到 foo 作用域
  console.log(x); // ❌ ReferenceError: x is not defined
}
  • var y 被提升并绑定到 foo 的函数环境,所以能在 if 外访问
  • let x 绑定在 if 块的环境记录中,foo 的作用域链里不包含该块环境(除非当前执行流就在该块内)
  • 这种差异导致你在调试时看到的“作用域面板”中,块级变量只在对应块内可见

常见误判点:this 不参与作用域链查找

很多人混淆 this 和词法作用域,以为 this 也会沿作用域链向上找。其实完全不是一回事:this 是运行时绑定的执行上下文对象,由调用方式决定(如 obj.method() 中 this 是 obj),而作用域链只管标识符(变量名、函数名)的解析。

  • function f() { console.log(x); } 查 x → 走作用域链
  • function f() { console.log(this.x); } 查 this.x → 先确定 this 是谁,再用属性访问规则(原型链)找 x
  • 箭头函数没有自己的 this,但它也不是靠作用域链“找”来的——它是直接继承外层函数的 this 值,属于绑定行为,不是查找行为

真正容易被忽略的是:作用域链只在**变量标识符解析阶段**起作用,一旦进入属性访问(obj.prop)、with 语句或 eval,就脱离了这条链。这些机制现在基本不用,但理解它们的边界,反而更能看清词法作用域的“纯粹性”。

Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南

相关文章

PHP速学视频免费教程(入门到精通)
PHP速学视频免费教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

相关专题

更多
mysql标识符无效错误怎么解决
mysql标识符无效错误怎么解决

mysql标识符无效错误的解决办法:1、检查标识符是否被其他表或数据库使用;2、检查标识符是否包含特殊字符;3、使用引号包裹标识符;4、使用反引号包裹标识符;5、检查MySQL的配置文件等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2023.12.04

18220

5

Python标识符有哪些
Python标识符有哪些

Python标识符有变量标识符、函数标识符、类标识符、模块标识符、下划线开头的标识符、双下划线开头、双下划线结尾的标识符、整型标识符、浮点型标识符等等。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.02.23

1283

5

java标识符合集
java标识符合集

本专题整合了java标识符相关内容,想了解更多详细内容,请阅读下面的文章。

2025.06.11

9750

9

c++标识符介绍
c++标识符介绍

本专题整合了c++标识符相关内容,阅读专题下面的文章了解更多详细内容。

2025.08.07

3882

7

c语言const用法
c语言const用法

const是关键字,可以用于声明常量、函数参数中的const修饰符、const修饰函数返回值、const修饰指针。详细介绍:1、声明常量,const关键字可用于声明常量,常量的值在程序运行期间不可修改,常量可以是基本数据类型,如整数、浮点数、字符等,也可是自定义的数据类型;2、函数参数中的const修饰符,const关键字可用于函数的参数中,表示该参数在函数内部不可修改等等。

2023.09.20

2478

7

堆和栈的区别
堆和栈的区别

堆和栈的区别:1、内存分配方式不同;2、大小不同;3、数据访问方式不同;4、数据的生命周期。本专题为大家提供堆和栈的区别的相关的文章、下载、课程内容,供大家免费下载体验。

2023.07.18

7067

5

堆和栈区别
堆和栈区别

堆(Heap)和栈(Stack)是计算机中两种常见的内存分配机制。它们在内存管理的方式、分配方式以及使用场景上有很大的区别。本文将详细介绍堆和栈的特点、区别以及各自的使用场景。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

2023.08.10

2908

6

go语言闭包相关教程大全
go语言闭包相关教程大全

本专题整合了go语言闭包相关数据,阅读专题下面的文章了解更多相关内容。

2025.07.29

5233

19

js正则表达式
js正则表达式

php中文网为大家提供各种js正则表达式语法大全以及各种js正则表达式使用的方法,还有更多js正则表达式的相关文章、相关下载、相关课程,供大家免费下载体验。

2023.06.20

5036

8

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
WebStorm 官方调试文档
WebStorm 官方调试文档

共0课时 | 0人学习

React 教程
React 教程

共58课时 | 12.5万人学习

TypeScript 教程
TypeScript 教程

共19课时 | 6.8万人学习