词法作用域的核心是函数能访问的变量取决于其在源代码中的定义位置,而非调用位置;该作用域链在函数声明时即固化,运行时不受调用方式影响,与动态的 this 形成鲜明对比。

词法作用域的核心就一句话:函数能访问哪些变量,取决于它在源代码里“写在哪里”,而不是“在哪儿被调用”。这个关系在代码解析阶段就固定了,运行时不会因为调用位置变化而改变。
定义时就锁死查找路径
JavaScript 引擎在读取函数声明(比如 function foo() { ... })的那一刻,就根据其所在的嵌套层级,构建好一条词法环境链。这条链从当前函数开始,逐级向上指向外层函数或全局环境。
- 写在全局下的函数,它的作用域链只包含全局环境
- 写在一个函数内部的函数,它的作用域链天然包含该外层函数的词法环境
- 这个链条不是靠运行时“看谁正在调用我”临时拼出来的,而是定义时就固化下来的结构
调用位置完全不影响变量查找
哪怕把一个函数传到十层深的回调里、塞进定时器、绑到事件上,它内部找变量依然走最初定义时确定的那条路。
- let value = 1;
- function foo() { console.log(value); }
- function bar() { let value = 2; foo(); }
- bar(); // 输出 1,不是 2
因为 foo 是在全局写的,它根本“看不见”bar 里的 value —— 那个变量不在它的词法环境链上。
和 this 的动态性形成鲜明对比
this 的值确实随调用方式变化:直接调用、方法调用、call/apply、箭头函数继承……都可能让 this 指向不同对象。但变量查找不走这条路。
- 普通变量(如
value、count)严格按词法作用域链查找,静态不变 -
this.xxx中的this是动态的,但一旦this确定了,查属性仍走该对象的原型链,不是作用域链
闭包是词法作用域的自然结果
当一个函数返回内部函数,而内部函数引用了外层变量,这些变量之所以能一直存活,正是因为引擎必须保留它定义时所依赖的整个词法环境。
- 不是靠记住“调用时外层还在执行”,而是靠定义时就建立并冻结的作用域链
- 哪怕外层函数早已执行完毕、执行上下文被销毁,只要闭包还存在,那些变量就继续保留在内存中
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











