0

0

JS如何实现词法作用域?作用域链

月夜之吻

月夜之吻

发布时间:2025-08-14 18:13:02

|

768人浏览过

|

来源于php中文网

原创

javascript中的词法作用域在函数定义时确定变量访问权限,作用域链则是执行时查找变量的路径,二者共同实现闭包并区分全局、函数和块级作用域,使代码行为可预测且支持精细的变量管理。

JS如何实现词法作用域?作用域链

JavaScript中,词法作用域是它处理变量可见性的核心机制,简单来说,它决定了你代码里的变量在哪个地方能被访问到。而作用域链,就是JS引擎在查找变量时,沿着这个词法作用域层层往上找的一条“路径”。它不是在代码运行的时候才决定的,而是在你写代码,也就是定义函数的那一刻,就已经固定下来了。这让我们的代码行为变得非常可预测,这也是JS能构建复杂应用的基础。

解决方案

理解词法作用域和作用域链,首先得明白JS里“作用域”这个概念。它不像我们日常说话那么随意,而是代码块、函数定义时,变量可被访问的区域。词法作用域(Lexical Scope),顾名思义,就是“定义时”的作用域。当你写下一段代码,定义一个函数时,这个函数的作用域就已经确定了,它会记住自己被定义时的环境,也就是它“出生”的地方。无论这个函数将来在哪里被调用,它查找变量的“家谱”都不会变。

举个例子,你有一个外部函数

outer
,里面定义了一个变量
x
,然后
outer
内部又定义了一个内部函数
inner
inner
函数天生就知道
x
存在,因为它是在
outer
里面定义的。即使你把
inner
函数作为返回值,拿到
outer
外面去执行,它依然能访问到那个
x
。这就是词法作用域的魅力,它让闭包(Closures)成为可能。

function outer() {
  let x = 10; // x 定义在 outer 的作用域
  function inner() { // inner 定义在 outer 的作用域内
    console.log(x); // inner 可以访问到 x
  }
  return inner; // 返回 inner 函数
}

const myInner = outer(); // myInner 现在是 inner 函数
myInner(); // 输出 10,即使 outer 已经执行完毕,inner 仍然能访问到 x

作用域链(Scope Chain)则是JS引擎在执行代码、查找某个变量时所遵循的规则。当JS引擎需要查找一个变量的值时,它会从当前执行上下文的作用域开始找。如果当前作用域找不到,它就会沿着作用域链向上,去父级作用域找,直到找到全局作用域为止。如果一直找到全局作用域都还没找到,那就会抛出一个

ReferenceError

这个“链”是怎么形成的呢?当一个函数被创建时,它会包含一个内部属性

[[Environment]]
,这个属性引用了它被创建时的那个词法环境(Lexical Environment)。这个词法环境,本质上就是它父级作用域的引用。所以,当我们执行一个函数时,它的执行上下文会创建一个新的词法环境,并把它的外部环境引用(outer environment reference)指向那个
[[Environment]]
属性所引用的词法环境。这样就形成了一个链条:当前作用域 -> 父级作用域 -> 父父级作用域 -> ... -> 全局作用域。

let globalVar = '我是全局变量';

function funcA() {
  let aVar = '我是函数A的变量';
  function funcB() {
    let bVar = '我是函数B的变量';
    console.log(bVar);   // 1. 在funcB当前作用域找到bVar
    console.log(aVar);   // 2. 在funcB作用域找不到aVar,向上到funcA作用域找到
    console.log(globalVar); // 3. 在funcA作用域找不到globalVar,向上到全局作用域找到
    // console.log(nonExistentVar); // 如果这里有,会抛出ReferenceError
  }
  funcB();
}

funcA();

这个过程,就像你在家里找东西,先在自己房间找,找不到就去客厅找,再找不到就去地下室或者阁楼找,最后如果还没找到,就只能说“没有这东西”了。

Beyond商城 2008修改版
Beyond商城 2008修改版

感谢广大歌迷长期以来对网站的支持和帮助,很多朋友曾经问我要过这个商城程序,当时由于工作比较忙,一直没空整理,现在好啦,已全部整理好了,在这里提供给有需要的朋友,没有任何功能限制,完全可以使用的,只是有些商品的广告需自己修改一下,后台没有办法修改,需要有HTML基础才可以修改,另外,哪位朋友在使用的时候,发现了BUG请与我们联系,大家共同改进,谢谢!后台管理地址:http://你的域名/admin/

下载

词法作用域如何实现JavaScript中的闭包?

谈到词法作用域,就不能不提闭包。可以说,闭包是词法作用域最直接、最强大的应用之一,它们俩简直是“焦不离孟,孟不离焦”。闭包的本质,就是函数和其被创建时所处的词法环境的组合。由于词法作用域的特性,当一个内部函数被定义时,它会“记住”其外部作用域的变量。即使外部函数执行完毕,其作用域理论上应该被销毁,但如果内部函数(闭包)仍然存在,并且引用了外部作用域的变量,那么这些变量就不会被垃圾回收,而是会一直被保留下来,供闭包使用。

这就像是给一个函数拍了一张“全家福”,照片里不仅有函数自己,还有它周围的环境(变量)。无论这个函数被带到哪里,这张“全家福”都会跟着它,让它随时都能回忆起并访问到那些变量。

function createCounter() {
  let count = 0; // count 定义在 createCounter 的词法作用域中
  return function() { // 这是一个匿名函数,它形成了一个闭包
    count++; // 访问并修改了外部作用域的 count 变量
    console.log(count);
  };
}

const counter1 = createCounter();
counter1(); // 输出 1
counter1(); // 输出 2

const counter2 = createCounter(); // 创建一个新的计数器,有独立的 count
counter2(); // 输出 1
counter1(); // 输出 3 (counter1 自己的 count 还在继续)

闭包在实际开发中非常有用,比如模块化、私有变量的实现、函数柯里化、事件处理等。它允许我们创建拥有“记忆”的函数,能够维护自己的状态,而不会污染全局作用域。理解了词法作用域,闭包的很多“神奇”行为就变得理所当然了。

JavaScript中的全局作用域、函数作用域与块级作用域有何区别

在JS中,作用域的划分方式主要有三种,它们共同构成了词法作用域的不同层次,也影响着变量的作用域链:

  1. 全局作用域 (Global Scope): 这是最外层的作用域。在浏览器环境中,通常是

    window
    对象;在Node.js中是
    global
    对象。在全局作用域中声明的变量和函数,在程序的任何地方都可以被访问到。在ES6之前,使用
    var
    声明的变量,即使在函数内部没有使用
    var
    声明,也会自动成为全局变量(不推荐)。 全局作用域污染是一个常见问题,因为过多的全局变量容易导致命名冲突和难以维护的代码。

  2. 函数作用域 (Function Scope): 这是JS中最基础的作用域单元。每个函数在被定义时都会创建一个新的作用域。在函数内部使用

    var
    声明的变量,只在该函数内部可见,外部无法直接访问。函数作用域是隔离变量的有效手段,避免了变量的冲突。ES6之前,这是唯一一种能创建新作用域的方式(除了全局)。

    var globalMessage = "Hello from global";
    
    function greet() {
      var greeting = "Hello from function"; // 函数作用域变量
      console.log(greeting);
      console.log(globalMessage); // 可以访问全局变量
    }
    
    greet();
    // console.log(greeting); // 报错:greeting is not defined
  3. 块级作用域 (Block Scope): 这是ES6引入的重大改进,主要通过

    let
    const
    关键字实现。块级作用域指的是由
    {}
    包裹的代码块(如
    if
    语句、
    for
    循环、
    while
    循环、甚至是一个独立的
    {}
    )所创建的作用域。在块级作用域中声明的
    let
    const
    变量,只在该代码块内部有效,外部无法访问。这极大地减少了
    var
    带来的变量提升(hoisting)和变量覆盖等问题,让代码的变量管理更加精细和可控。

    if (true) {
      var oldVar = "我是var,函数作用域";
      let newLet = "我是let,块级作用域";
      const newConst = "我是const,也是块级作用域";
      console.log(newLet); // 正常访问
      console.log(newConst); // 正常访问
    }
    
    console.log(oldVar); // 正常访问,因为var是函数作用域(或全局)
    // console.log(newLet); // 报错:newLet is not defined
    // console.log(newConst); // 报错:newConst is not defined
    
    for (let i = 0; i < 3; i++) {
      // i 每次循环都是一个新的块级作用域变量
      setTimeout(() => console.log(i), 100); // 正常输出 0, 1, 2
    }
    // 如果这里用 var i,会输出 3, 3, 3,因为 i 是函数作用域,循环结束后 i 变成了 3

理解这三种作用域的区别,对于编写健壮、可维护的JavaScript代码至关重要。

let
const
的引入,让JS的变量作用域管理变得更加直观和安全,也让开发者能更好地利用词法作用域的特性来组织代码。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
es6新特性
es6新特性

es6新特性有:1、块级作用域变量;2、箭头函数;3、模板字符串;4、解构赋值;5、默认参数;6、 扩展运算符;7、 类和继承;8、Promise。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

106

2023.07.17

es6新特性有哪些
es6新特性有哪些

es6的新特性有:1、块级作用域;2、箭头函数;3、解构赋值;4、默认参数;5、扩展运算符;6、模板字符串;7、类和模块;8、迭代器和生成器;9、Promise对象;10、模块化导入和导出等等。本专题为大家提供es6新特性的相关的文章、下载、课程内容,供大家免费下载体验。

196

2023.08.04

JavaScript ES6新特性
JavaScript ES6新特性

ES6是JavaScript的根本性升级,引入let/const实现块级作用域、箭头函数解决this绑定问题、解构赋值与模板字符串简化数据处理、对象简写与模块化提升代码可读性与组织性。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

223

2025.12.24

if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

787

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

98

2023.09.25

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

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

532

2023.09.20

全局变量怎么定义
全局变量怎么定义

本专题整合了全局变量相关内容,阅读专题下面的文章了解更多详细内容。

82

2025.09.18

python 全局变量
python 全局变量

本专题整合了python中全局变量定义相关教程,阅读专题下面的文章了解更多详细内容。

97

2025.09.18

AO3官网入口与中文阅读设置 AO3网页版使用与访问
AO3官网入口与中文阅读设置 AO3网页版使用与访问

本专题围绕 Archive of Our Own(AO3)官网入口展开,系统整理 AO3 最新可用官网地址、网页版访问方式、正确打开链接的方法,并详细讲解 AO3 中文界面设置、阅读语言切换及基础使用流程,帮助用户稳定访问 AO3 官网,高效完成中文阅读与作品浏览。

89

2026.02.02

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++教程
C++教程

共115课时 | 15.5万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

微信小程序开发之API篇
微信小程序开发之API篇

共15课时 | 1.3万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号