← 返回目录

8. 作用域与作用域链

作用域就是变量能被看到的范围。全局变量到处能用,局部变量只在函数内部能用。

核心三种:
全局作用域——最外面,到处都能用
函数作用域——函数内部,外面看不到
块级作用域——let/const 在 {} 里生效

坑:var 没有块级作用域、内部能访问外部、外部不能访问内部、同名变量内部覆盖外部

8.1 互动演示(三种作用域 + 作用域链就近查找)

点按钮看:全局/局部/块级的差别,以及「就近查找、不会向内」的作用域链。

8.2 知识点逐条讲解(配合代码)

① 三种地盘

地盘在哪特点
全局(公共大厅)整个 script哪都能用,页面关才销毁
函数局部(自己工位)function 里面只有函数内能用,执行完就收走
块级(会议室)if/for 后的 {}只对 let/const 生效,var 不认
// var 不认 {}:括号外面照样能用
if (true) {
  // var 写在哪都算全局
  let num = 123;
}

// 123,外面照样取得到
console.log(num);

// var 认 {}:出了括号就找不到
if (true) {
  // var 只在这对括号里有效
  let n = 10;
}

// 报错:n is not defined(出门就没了)
console.log(n);

② 作用域链:就近找人,一层层往外找

函数套函数时,里面那层能用外面那层的变量。找东西的规矩:先翻自己抽屉,没有就翻上一层,一直翻到公共大厅;绝不会往更里面翻

// 全局放了个 num
let num = 456;

function f1() {
  // f1 里又放了个同名 num
  let num = 123;
  function f2() {
    // f2 先找自己 → 再找 f1 → 拿到 123
    console.log(num);
  }
  // 不去全局拿 456
  f2();
}

f1();

如果你在里面又起了个同名变量,外面那个就被「挡住」了。因为就近原则,里面用自己的,看不到外面的。想让里面用外面的,里面就别再定义同名的。

⑥ X.3 实战:用在哪 / 常见坑 / 怎么解决

① 用在哪:读别人代码找变量为什么找不到、防止多个函数互相污染同名变量。

② 常见坑:let 出了 {} 还想用,报 ReferenceError;函数内外同名变量搞不清用了哪个。

③ 怎么解决:养成用 let/const 的习惯;变量找不到就沿作用域链从内往外查同名。

一句话记住:全局哪都能用、局部出函数就没、块级只认 let/const 不认 var;作用域链就近找、只往外不往里;同名里面挡住外面

本页重点

API作用参数返回值代码示例
var旧声明,作用域松、会提升变量名
let x = 1;  // 函数作用域
let块级声明,推荐变量名
let x = 1;  // 块作用域
const常量,定了不能再赋值变量名
const PI = 3.14;  // 不能改
作用域链就近找变量,不会向内找变量值
let a = 1;

function f() {
  console.log(a);  // 找上一级
}