如何理解javascript中的变量和作用域?【教程】

11次阅读

javaScript变量与作用域直接影响代码行为:var受提升和函数作用域影响,let/const有TDZ和块级作用域,闭包依赖词法作用域链,异步需兼顾执行、绑定与内存引用时机。

如何理解javascript中的变量和作用域?【教程】

javascript 中的变量和作用域不是“概念背诵题”,而是每次写 letvar、函数嵌套、异步回调时,都会真实影响代码是否报错、值是否被覆盖、闭包能否生效的底层机制。

为什么 var 声明的变量会“提升”且能跨块访问?

var 的行为由“变量提升(hoisting)”和“函数作用域”共同决定:声明会被移到当前函数顶部,但赋值不提升;它不认 {} 块,只认 function 边界。

  • iffor 块里用 var 声明,变量仍可在块外访问
  • 重复 var 同名变量不会报错,后一次声明会覆盖前一次(但仅限声明,赋值仍按顺序执行)
  • console.log(a); var a = 1; 输出 undefined,不是报错——因为 var a; 被提升了,但 a = 1 还没执行

letconst 真的“没有提升”吗?

它们有“暂时性死区(TDZ)”:声明确实被提升了,但直到实际执行到那行代码前,访问该变量会直接抛出 ReferenceError。这不是语法错误,是运行时错误。

  • console.log(b); let b = 2; → 报错 ReferenceError: Cannot access 'b' before initialization
  • const 必须在声明时赋值,且不能重新赋值(注意:对象属性仍可修改)
  • for (let i = 0; i console.log(i), 0); 输出 0 1 2,而换成 var 会输出三个 3——这是块级绑定带来的闭包行为差异

函数内部怎么确定 this 和变量查找顺序?

变量查找走“词法作用域链”,从当前函数开始,逐层向上找 let/const/var 声明;而 this 是调用时才绑定的,和作用域无关。

立即学习Java免费学习笔记(深入)”;

  • 嵌套函数中访问外部变量,靠的是外层函数执行时生成的闭包环境,不是靠 this
  • function foo() { const x = 1; return function() { return x; }; } 中,内层函数能读 x,是因为它记住了外层作用域的引用
  • 箭头函数不绑定自己的 this,也不创建自己的作用域(没有 arguments,不能用 yield),它直接沿用外层函数的 this 和词法环境

模块顶层、IIFE、class 内部的作用域边界在哪?

ES 模块(.mjstype="module")顶层是块级作用域,不是全局;class 内部的 method 是函数作用域,但 class 声明本身不创建作用域;IIFE 是手动制造函数作用域的老办法。

  • importexport 只能在模块顶层,不能在 if 或函数里——否则报 Unexpected Token
  • class A { x = 1; method() { console.log(this.x); } } 中,x 是实例属性,不在 method 的词法作用域内,必须通过 this 访问
  • IIFE:(function(){ let tmp = 1; })(); 中的 tmp 确实无法从外部访问,但它解决的是“避免污染全局”,不是替代 let 的块级作用域

真正容易被忽略的,是异步场景下作用域和闭包的组合效应:比如在循环中为每个定时器捕获正确的索引值,或在 fetch 回调里访问外层 const 变量——这时候光懂“块级作用域”不够,得清楚执行时机、绑定时机、内存引用三者怎么咬合。

text=ZqhQzanResources