前端进阶之旅前端进阶之旅
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
基础篇
进阶篇
高频篇
精选篇
手写篇
面经篇
AI 篇
原理篇
每日一题
小程序题库
知识卡片
  • 场景篇按分类整理的大前端场景考点
  • 历年面经按年份追踪真实考点
  • 算法题库NEW在线编码即时判题
  • 专项自测100 题快速查漏
  • 前端基础
    • HTTP从报文一路讲到 HTTPS
    • 浏览器渲染、事件循环、进程
    • 计算机基础Linux、网络、操作系统
  • 进阶专项
    • 设计模式23 种模式怎么用
    • 前端系统进阶学习大型项目工程化
    • 前端综合文章长期沉淀的实践文
  • 工程与工具
    • Node学习指南从环境搭建到服务端
    • NPM工作流script、依赖与发布
    • Docker容器化部署上手
    • Canvas图形与动画实战
  • 路线与导图
    • 思维导图知识点全景图
    • 学习路线按图索骥不跑偏
  • 动态
    • 公众号动态公众号历史文章
    • 博客动态站长的技术博客
    • 开发者导航常用工具与文档站
  • AI 助手随时提问,即时解析
  • AI 模拟面试模拟真实面试 + 报告
  • AI 知识地图串起全站知识点
  • AI 定制路线按你的简历现排
AI 热点
旧版
首页程序员面试题库var let const 作用域与提升区别
JavaScript函数与作用域

var、let、const 的作用域有什么不同?

var 是函数作用域,if、for 的花括号关不住它;let 和 const 是块级作用域,出了花括号就访问不到。const 只是不能重新赋值,对象里的属性照样能改。

前端进阶之旅 · 一题精讲更新于 2026.09.29
JavaScript#函数与作用域
先看核心答案读代码示例
理解线索

三个关键字差在哪

  1. var函数作用域,提升后先是 undefined,可以重复声明
  2. let块级作用域,有暂时性死区,可以重新赋值
  3. const和 let 一样的作用域规则,声明时必须赋值,之后不能再赋值

在普通 <script> 顶层写 var,变量会变成 window 的属性;顶层的 let 和 const 不会。

核心回答

先记住这个答案

区别主要在三件事上。第一是作用域:var 属于最近的函数,if、for 这些花括号挡不住它;let 和 const 属于最近的一对花括号,出了块就访问不到。第二是提升:三者都会提升,但 var 提升后先被初始化成 undefined,let 和 const 在声明那一行执行之前处于暂时性死区,访问就抛 ReferenceError。第三是赋值:let 可以重新赋值,const 声明时必须赋值、之后不能再赋值,但它指向的对象内容仍然可以改。

  • var 只认函数边界,块挡不住它
  • let 和 const 只在所在的 {} 里有效
  • 声明前访问 let 会抛 ReferenceError,var 得到 undefined
  • const 锁的是变量,不是对象内容

用一个函数看清三者的边界

在 if 块里分别声明三个变量,再到块外面去读,同时试试在声明前访问。

块里声明,块外读取JavaScript
function demo() {
  console.log(early) // var 已提升,值是 undefined
  try {
    console.log(late)
  } catch (err) {
    console.log(err.name) // let 还在暂时性死区
  }
  let late = 'let'

  if (true) {
    var early = 'var'
    let inner = 'let in block'
    const config = { on: false }
    config.on = true // 改属性可以
    console.log(inner, config.on)
  }
  console.log(early) // var 出了 if 仍然可见
  console.log(typeof inner) // let 出了块就没有了
}
demo()
查看输出与解释
undefined
ReferenceError
let in block true
var
undefined

early 是在 if 块里声明的,但它属于整个 demo 函数,函数一开始就存在,只是值为 undefined,赋值后块外也能读到。late 在声明前读取直接报错,这段报错的区间就叫暂时性死区。inner 离开 if 块就不存在了,typeof 对未声明的变量返回字符串 undefined。config 不能被重新赋值成别的对象,但改它的属性没问题。

暂时性死区到底挡住了什么

暂时性死区是指从作用域开始到 let 或 const 声明语句执行之前的那一段,变量已经存在,但不允许读写。它的意义是把「先用后声明」这种写法从静默的 undefined 变成明确的报错。

遮蔽和死区一起出现的坑
外层有一个 let x = 1,内层块里写 console.log(x); let x = 2,很多人以为会打印外层的 1,实际会报 ReferenceError。因为内层块里声明了自己的 x,整个块里的 x 都指向这个还没初始化的内层变量,外层的 x 已经被遮住了。
循环里的区别
for (let i = 0; ...) 每一轮循环都会创建一个新的 i,所以循环里的异步回调各自拿到自己那一轮的值。var 整个函数只有一个 i,回调执行时读到的都是循环结束后的值。这也是现在循环变量一律用 let 的原因。
回答前,多想一步

容易答错的地方

说 let 和 const 不会提升
它们会提升,作用域一开始变量就已经存在,所以才会遮住外层的同名变量。只是没有被初始化,声明前访问会报错。说「不提升」解释不了上面遮蔽的那个例子。
说 const 声明的对象不可变
const 限制的是变量不能指向别的值,对象本身的属性、数组的元素都能改。要让对象不可改,用 Object.freeze,而且它只冻结一层,嵌套对象还要递归处理。
说 var 没有作用域
var 有作用域,是函数作用域。函数里声明的 var,函数外面访问不到。它只是不受 if、for 这类块的限制。
试着用自己的话回答

面试官还会怎么问?

同一个作用域里重复声明会怎样?

var 重复声明不报错,后面的赋值覆盖前面的。let 和 const 重复声明是语法错误,代码在解析阶段就失败,一行都不会执行。var 和 let 同名混用也会报错。

项目里该怎么选?

默认用 const,需要重新赋值的变量(计数器、累加结果、循环变量)用 let,新代码不再用 var。这样读代码的人看到 const 就知道这个变量不会再指向别的东西。

顶层的 var 和 let 有什么区别?

在普通脚本顶层,var 声明的变量会成为全局对象的属性,window.x 能读到;let 和 const 声明的也是全局变量,但不挂在 window 上。在 ES 模块里,顶层声明都只属于这个模块,不会变成全局变量。

从一道题,走向一组知识

把知识连起来

函数与作用域

生成器里的 yield* 是干什么的?和 yield 有什么区别?

生成器函数同样是一层函数作用域,里面用 var 声明的变量不会漏到外面。

模块与语言机制

模块里写了顶层 await,为什么导入它的父模块要一直等?能避免吗?

模块顶层有自己的作用域,顶层 var 不会挂到 window 上,顶层 await 也只在模块里能用。

参考资料

  • JavaScript:函数与作用域参考资料

示例用于理解所注明的运行环境与边界;延伸学习可结合原文中的更多案例。

本题目录
  1. 先记住这个答案
  2. 用一个函数看清三者的边界
  3. 暂时性死区到底挡住了什么
  4. 容易答错的地方
  5. 面试官还会怎么问
  6. 把知识连起来
读懂,再试着讲出来

先看核心答案,再读代码。最后展开追问,检查自己有没有遗漏边界。

试着回答追问
浏览全部面试题理解原理,也关注真实的使用场景。回到顶部 ↑