Loading [MathJax]/jax/output/CommonHTML/config.js
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >【前端】JavaScript 变量声明与函数声明的提升机制:深入探讨提升优先级与其行为

【前端】JavaScript 变量声明与函数声明的提升机制:深入探讨提升优先级与其行为

作者头像
CSDN-Z
发布于 2025-06-02 02:12:17
发布于 2025-06-02 02:12:17
10000
代码可运行
举报
文章被收录于专栏:AIGCAIGC
运行总次数:0
代码可运行

博客主页: [小ᶻ☡꙳ᵃⁱᵍᶜ꙳] 本文专栏: 前端

💯前言

  • JavaScript 编程语言中,提升(hoisting)是一个关键的编译特性,它深刻影响代码的行为,直接影响到变量和函数的可见性和可用性。作为 JavaScript 编译与执行过程的重要组成部分,理解提升机制对于编写正确且高效的代码至关重要。尤其是在编写复杂应用时,这一概念的掌握有助于避免潜在的错误,并确保程序逻辑的明确性和可预测性。 本文旨在对 JavaScript 提升机制进行详细探讨,特别是关于变量声明var)和函数声明提升优先级,以及两者之间的复杂关系。我们将通过深入的分析代码示例,系统揭示提升机制的行为模式及其背后的原理JavaScript

💯提升(Hoisting)概述

提升(Hoisting)JavaScript 编译阶段的行为,它涉及到将代码中的变量声明函数声明提升到所在作用域全局作用域的最顶端。这意味着在代码执行之前,JavaScript 引擎会对代码进行预处理,使得这些声明可以在其实际声明之前访问。通俗地说,JavaScript 在编译时会扫描整个作用域,将变量和函数的声明部分提前处理。

这种提升带来的效果使得在代码的任何位置都能够访问变量和函数,甚至是在它们的实际声明之前,从而形成了**“提前可用”的特性。这种机制为 JavaScript 提供了灵活性**,但也带来了代码可读性调试上的挑战,特别是在同名变量和函数存在时,可能会引入意料之外的行为。因此,理解提升的具体原理及其对代码的影响是开发人员的基本功

在进一步探讨提升机制之前,有必要明确 JavaScript 中三种主要的声明方式varletconst,它们在提升时有着显著的差异。此外,函数声明函数表达式在提升方面也表现出不同的行为模式。本文将聚焦于 var 和函数声明的提升,解析它们的优先级及相互关系


💯提升机制——函数声明 vs 变量声明

在 JavaScript 中,函数和变量的声明都会被提升,但它们的提升方式和处理规则并不相同。

  • 函数声明:函数声明会在编译阶段被完整提升到作用域的最顶端,包括函数的函数体在内。因此,函数可以在其声明之前调用。这种行为赋予了开发者很大的灵活性,尤其是在编写递归函数或将函数作为回调时,可以确保函数在作用域中的可见性和可调用性。
  • var 变量声明var 声明的提升仅限于声明部分,而赋值部分不会被提升。这意味着在作用域的最顶端,变量会被默认初始化为 undefined,直到代码执行到赋值语句时,变量的值才会被真正更新。因此,var 提升后的行为往往会导致一些令人困惑的未定义状态。

通过下面的代码示例,我们可以更好地理解函数声明与 var 声明的提升效果及其相对优先级。


💯代码示例:函数与 var 的提升

以下代码展示了涉及函数声明和 var 声明的提升过程,展示了函数优先于变量的提升优先级:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(foo);  // 输出函数 foo 的定义

function foo() {
  console.log("Hello, World!");
}

var foo = 10;

console.log(foo);  // 输出 10

提升后的代码解析

在上面的代码中,JavaScript 引擎在编译阶段对代码进行了提升,提升后的代码等效于:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function foo() {
  console.log("Hello, World!");
}

var foo;

console.log(foo);  // 输出函数 foo 的定义

foo = 10;

console.log(foo);  // 输出 10

分析

  • 在编译阶段,函数声明 function foo() 会被提升到作用域的最顶端,因此在代码执行之前,函数 foo 已经在当前作用域内被定义,并且可以在 console.log(foo) 之前使用。
  • 接下来,var foo 的声明也被提升,但它仅仅是声明变量,而不会覆盖函数声明,因此在编译结束时,foo 仍然是指向函数的引用。
  • 执行代码时,第一次 console.log(foo) 输出的是函数 foo 的定义。
  • 随后,当 foo 被赋值为 10 后,再次调用 console.log(foo),这时输出的就是 10

💯同名函数和变量声明的行为

当函数声明和 var 变量声明同名时,函数声明会优先于变量声明被提升,且变量声明不会覆盖函数声明。然而,变量的赋值操作会在执行阶段覆盖函数的定义,这可能导致函数无法再被调用。

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function x() {
  x = 20;
}

var x;

console.log(x);  // 输出函数 x 的定义

x = 10;

console.log(x);  // 输出 10

x();  // 报错:TypeError: x is not a function

提升过程与执行分析

  1. 提升阶段
    • 函数 x 的声明会被提升到作用域的最顶端,因此在编译阶段,x 被初始化为一个函数。
    • 紧接着,var x 的声明也被提升,但它不会覆盖已经存在的函数定义,只是做了一个声明。
  2. 执行阶段
    • 第一次 console.log(x) 输出的是函数 x,因为此时 x 的值为函数。
    • x = 10 赋值后,x 的引用被修改为数字 10,因此覆盖了之前的函数定义。
    • 最后,当尝试调用 x() 时,由于 x 现在是一个数字而不是函数,因此抛出 TypeError: x is not a function

💯为什么函数声明的提升优先于变量声明?

函数声明的提升优先于变量声明的原因与 JavaScript 的执行模型息息相关。在 JavaScript 中,代码的执行分为编译阶段执行阶段。在编译阶段,JavaScript 引擎会进行词法分析,将所有的函数声明完整地提升到作用域的最顶端,确保它们在执行阶段可以被调用。

相比之下,var 声明在编译时也会被提升,但初始化部分会保留在原始位置。因此,在赋值之前,变量的初始值是 undefined

这种机制的设计使得函数在作用域内具有更高的优先级,从而确保开发者可以在代码的任何位置调用函数。这种灵活性对于编写结构化代码至关重要,但同时也要求开发者更小心谨慎,以免变量声明和函数声明的混合使用导致不可预料的行为


💯变量声明的不同类型——varletconst 的提升行为


letconst 的行为

var 声明不同,letconst 的提升行为更加严格。虽然 letconst 也会被提升,但它们在赋值之前处于暂时性死区(Temporal Dead Zone, TDZ)。在 TDZ 中访问这些变量会抛出 ReferenceError,这是为了确保变量在实际赋值之前不会被访问,从而避免未定义行为。

例如:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(a);  // 抛出 ReferenceError
let a = 10;

在这个例子中,a 虽然被提升,但由于在赋值前处于 TDZ,因此访问会导致 ReferenceError。这种行为使得 letconst 更加安全,防止在变量未被正确初始化之前对其进行访问。


为什么使用 letconst 更安全

letconst 相比于 var 提供了更加安全和合理的变量管理方式。首先,letconst 不会被初始化为 undefined,而是要求在赋值后才可以使用,这有效避免了许多常见的未定义错误。其次,TDZ 的存在使得这些变量在声明之前是不可访问的,这可以强制开发者遵循正确的变量声明和赋值顺序,增强代码的可读性和健壮性。


💯提升机制中的常见陷阱与最佳实践

理解提升机制的工作原理,有助于开发者识别并避免在 JavaScript 中的一些常见陷阱。以下列出了一些常见的陷阱以及相应的最佳实践,以帮助开发者编写更可靠的代码。


常见陷阱

变量提升导致的 undefined 错误

  • 使用 var 声明的变量在提升后会被初始化为 undefined,因此在赋值之前访问它们会返回 undefined。这种行为可能导致程序意外地处理未定义的值,产生难以察觉的 bug。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(b);  // 输出 undefined
var b = 20;

函数和变量同名时的混淆

  • 当函数和变量同名时,变量的赋值操作会覆盖函数的定义,这导致后续对该函数的调用会失败。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
function example() {
  console.log("I am a function");
}

var example = 10;

example();  // 抛出 TypeError: example is not a function

letconst 的暂时性死区(TDZ)

  • 当使用 letconst 声明变量时,变量在实际赋值之前处于 TDZ 中,访问这些变量会导致 ReferenceError,这可能会让开发者感到困惑。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
console.log(c);  // 抛出 ReferenceError
let c = 30;

最佳实践

  1. 避免使用 var
    • 使用 letconst 来代替 var,从而避免由于变量提升和初始化为 undefined 导致的错误。
  2. 保持函数与变量名称的唯一性
    • 为了避免函数和变量的命名冲突,尽量保持函数和变量具有唯一的名称,以免产生意外的覆盖行为。
  3. 将变量声明放在靠近使用的地方
    • 避免将变量声明分散在代码的不同部分,而是将变量声明靠近其首次使用的位置,以增加代码的可读性和维护性。
  4. 了解提升机制
    • 深入理解 JavaScript 提升机制可以帮助开发者编写更加可预测和稳定的代码,减少因提升导致的未定义行为。
  5. 提前声明并初始化变量
    • 在适当的位置声明并初始化变量,确保变量在使用之前已经被赋予正确的值,以减少提升机制带来的混淆。
  6. 小心使用 letconst 的暂时性死区
    • 在使用 letconst 时,要特别注意它们的 TDZ 行为,确保在变量声明和赋值之后再进行访问。

💯小结

JavaScript 中的提升机制是一个重要且复杂的概念,理解函数声明与变量声明的提升优先级对于避免代码中的潜在错误至关重要。提升机制使得函数声明在变量声明之前被提升,而 var 声明的变量只会在作用域中被初始化为 undefined,并在代码执行阶段完成赋值。因此,理解这些细节可以帮助开发者编写出更为稳定、健壮和易于维护的代码。

  • 为了最大程度地减少因提升带来的问题,建议开发者尽量使用 letconst,并确保函数和变量之间没有命名冲突。通过掌握提升机制的详细原理和行为,开发者可以更好地控制代码的执行顺序,编写出更加可靠和高效的 JavaScript 程序。
  • 提升机制是 JavaScript 的独特特性之一,它深刻体现了这门语言的动态性与灵活性。理解并正确应用这一特性,不仅有助于开发者更好地编写代码,也有助于增强团队协作时代码的质量与一致性。通过持续的实践和深入学习,开发者可以熟练掌握提升机制,从而避免潜在的错误,编写出健壮、高效且可维护的 JavaScript 应用程序。
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-12-10,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
小程序(2):云开发
所谓serverless就是无后台开发。通俗地说就是踢开后端闹革命。只需要一个前端就可以操作数据库小程序云开发就是这个概念的尝鲜者。云开发也是小程序近年最大的改变之一。
一粒小麦
2019/08/22
3.5K0
TCB系列学习文章——搭建你的第一个云开发小程序(二)
ps:此篇文章只是超简单的搭建一个云开发小程序,后续会一一讲解各部分的详细使用方法和使用场景。
F颜
2020/06/24
1.4K1
TCB系列学习文章——搭建你的第一个云开发小程序(二)
微信小程序与云开发
Java、NodeJS、JavaScript、HTML5、CSS3、VueJs、ReactJs、前端工程化、前端架构
达达前端
2019/08/05
9.5K0
微信小程序与云开发
2022年你还不会serverless?看看这篇保姆级教程(中)
找到云开发的环境ID,点击云开发控制台窗口里的设置图标,在环境变量的标签页找到环境名称和环境ID。
前端进阶之旅
2022/01/07
1.3K0
2022年你还不会serverless?看看这篇保姆级教程(中)
TCB系列学习文章——搭建你的第一个web端云开发(三)
这里需要特别注意,若已在微信开发者工具开通云开发环境,并且希望可以和web端使用同一个环境,在登录控制台的时候,请选择微信公众号登录
F颜
2020/06/28
1.3K0
TCB系列学习文章——搭建你的第一个web端云开发(三)
微信小程序云开发入门详细教程
通过以上清晰的对比,我们可以看出,如果小团队想要快速创建一个小程序的后台,用云开发是一个很好的选择。
bug开发工程师007
2024/11/13
4.5K3
【云+社区年度征文】2020年小程序开发-云开发技术总结
2020年注定是不平凡的一年,一场冠状疫情的爆发,让人们突然认识到生命的可贵,人们对生命重新有了新的认识。谱写了太多的悲伤,太多难过,太多的眼泪和辛酸。珍惜当下,敬畏生命,敬畏自然。
达达前端
2020/12/18
2.4K0
【云+社区年度征文】2020年小程序开发-云开发技术总结
实战丨如何制作一个完整的外卖微信小程序开发项目(已开源)
一开始项目并非基于云开发而开发的,目前考虑用云开发,因此,需要在项目中开启云开发的相关选项。
腾讯云开发TCB
2020/07/29
4.4K0
实战丨如何制作一个完整的外卖微信小程序开发项目(已开源)
刷题小程序【程序猿面试宝典】开发(一)| 项目概述与前期准备
AppID在登录注册号的小程序候可以看到,点击开发设置 -》复制 AppID
C you again 的博客
2021/07/23
6500
微信小程序知识云开发
小程序界面设计、交互、功能与他人的手机应用软件或在先发布的小程序构成实质性相似,构成小程序抄袭
达达前端
2019/08/18
6K0
【云+社区年度征文】基于云开发完成小程序用户注册登录
之前,如果我们想要开发一个小程序,运维人员需要考虑买什么样的服务器,匹配哪些资源,比如存储应用、数据库等,后端开发人员需要编写服务接口,前端人员需要编写页面,对接后端提供的接口,这个工作流程下来,需要至少一个月的时间。有了“小程序 · 云开发”以后,开发者不用考虑后端复杂的技术操作,一个前端开发者就可以轻松的完成从无到有、从开发到发布的过程。
青年码农
2020/11/25
4.5K14
【云+社区年度征文】基于云开发完成小程序用户注册登录
微信小程序云开发功能实践
前端开发者在进行小程序开发时,总是需要接触到小程序服务端的开发,如openId的获取、生成小程序码、微信支付等。这些功能必须要搭配后端服务进行开发的,这就可能会导致前端开发者不得不去接触、学习后端的开发语言:如Java、Python、PHP等,产生了额外的学习成本。
胡哥有话说
2019/07/25
7.8K3
微信小程序云开发功能实践
小程序云开发全套实战教程(最全)
在学习云开发的时候将自己的学习过程记录下来了,放在了网上,收获了一波好评,今天下午在办公室没有事情,也发现之前有人在博客里面评论,你这个教程还有一半哩,可能是csdn的自动搬运功能出来一点小问题,没有搬运成功吧,这里就手动复制粘贴成为一篇了,篇幅比较长,如果有不足或者不注意写错的地方,欢迎大家提出纠正哦。
王小婷
2019/01/28
16.4K2
『云函数』基本使用
经前面几篇文章的介绍,已经给大家介绍了云开发中的云数据库与云存储,那么了解完了云数据库云存储之后,接下来我介绍一下云开发中的另外一个重要的功能,云函数。
程序员NEO
2024/01/25
7772
『云函数』基本使用
微信小程序云开发—云函数连接MySQL
本文章代码已上传GitHub:https://github.com/aquanlerou/miniprogram-cloud-development
爱敲代码的猫
2020/04/22
5.3K0
使用原生开发高仿瑞幸小程序(四):编写云函数并连接云数据库
通过云函数,我们将拥有编写服务端代码的能力。我们可以在服务端执行一些逻辑,可以上传图片,可以调用其他网络服务的api,可以对数据库进行操作。重要的是,云函数的编写相当简洁,便利。 在这一节,我们将通过云函数获取“为你推荐”的产品数据,实现数据动态化。实现这一功能,我们需要学习以下三块内容:
一只图雀
2020/06/04
1.3K0
使用原生开发高仿瑞幸小程序(四):编写云函数并连接云数据库
零基础学做电商小程序,手把手教学!(内有福利)
本次课程为电商小程序的基础讲解,通过该教程学习云开发的基本知识、了解小程序开发步骤、掌握云模板的基本使用。
腾讯云开发TCB
2024/07/15
3720
零基础学做电商小程序,手把手教学!(内有福利)
【小程序云开发】云函数路由的高效配置
在小程序开发工具中,启动云开发默认模板,提供的云函数办法是一个请求对应一个云函数,比如说,我要获取用户登录数据,就添加一个login函数,然后前端就请求这个login获取,如果现在我要通过云函数删除我的使用用户,是不是就得重新再建一个函数如delete,然后这个delete就用于处理前端提交的用户删除任务,如果到时候任务多了,不就需要创建很多个云函数了吗?麻烦,所以我们想办法一个函数处理多个任务,这就需要使用云函数路由了。
许坏
2019/07/14
1.7K0
实战分享: 小程序云开发玩转订阅消息
微信官方为提升小程序模板消息能力的使用体验,对模板消息的下发条件进行了调整。原有的小程序模板消息接口于 2020 年 1 月 10 日下线,届时将无法使用旧的小程序模板消息接口发送模板消息,取而代之的是新的一次性订阅消息和长期订阅消息。
Booker Zhao
2019/10/23
1.6K0
实战分享: 小程序云开发玩转订阅消息
005微信小程序云开发API数据库-查询记录-聚合-统计记录数量
微信小程序云开发API数据库是一个方便快捷的数据库解决方案,可以让开发者在小程序中直接使用云端数据库功能,无需自己搭建和管理服务器。在微信小程序云开发API数据库中,我们可以查询指定的记录,以便获取相关的数据和信息。本文将通过案例和代码的方式,详细介绍微信小程序云开发API数据库的查询记录方法。
度假的小鱼
2024/12/25
5240
005微信小程序云开发API数据库-查询记录-聚合-统计记录数量
推荐阅读
相关推荐
小程序(2):云开发
更多 >
交个朋友
加入腾讯云官网粉丝站
蹲全网底价单品 享第一手活动信息
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验