前言
在 JavaScript 中,作用域是非常基础但又非常重要的知识点。
闭包、变量查找、函数执行、模块化等内容,都和作用域密切相关。
本文主要讲清楚:
- 什么是作用域
- JavaScript 有哪些作用域
- 什么是作用域链
- 变量查找规则是什么
一、什么是作用域?
作用域可以理解为:
变量和函数可以被访问的范围。
也就是说,一个变量不是在任何地方都能访问,它的可访问范围由作用域决定。
例如:
let a = 10;
function test() {
let b = 20;
console.log(a); // 可以访问
}
test();
// console.log(b); // 报错
这里:
-
a在全局作用域中 -
b在函数作用域中 -
函数内部可以访问全局变量
-
全局不能访问函数内部变量
二、JavaScript 中的几种作用域
1)全局作用域
定义在函数外部的变量,通常属于全局作用域。
let name = 'Tom';
function say() {
console.log(name);
}
全局作用域中的变量,在当前脚本中通常都可以访问。
2)函数作用域
在函数内部声明的变量,只能在函数内部访问。
function test() {
let age = 18;
console.log(age);
}
test();
// console.log(age); // 报错
3)块级作用域
使用let和const声明的变量,会形成块级作用域。
{
let a = 1;
const b = 2;
}
// console.log(a); // 报错
// console.log(b); // 报错
if、for、while、{}都可以形成块级作用域。
三、var、let、const 的作用域区别
var
- 没有块级作用域
- 只有全局作用域和函数作用域
if (true) {
var a = 10;
}
console.log(a); // 10
let / const
- 有块级作用域
if (true) {
let b = 20;
}
// console.log(b); // 报错
四、什么是作用域链?
当在当前作用域中查找某个变量时,如果找不到,就会去上一级作用域查找,直到全局作用域。
这个逐级向上查找的过程,就叫做 作用域链。
五、作用域链示例
let a = 1;
function outer() {
let b = 2;
function inner() {
let c = 3;
console.log(“结果”,a, b, c);
}
inner();
}
outer();
输出:
结果,1 2 3
查找过程:
-
找
c:先在inner自己内部找,找到 -
找
b:inner找不到,去outer找,找到 -
找
a:inner找不到,outer找不到,去全局找,找到
这就是作用域链。
六、作用域链的本质
作用域链的本质是:
函数在定义时,就已经确定了它能访问哪些外部变量。
注意,是定义时,不是调用时。
这也是闭包能成立的基础。
七、总结
作用域决定了变量的可访问范围,作用域链决定了变量的查找路径。
重点记住:
- 全局作用域
- 函数作用域
- 块级作用域
- 变量查找是逐级向上找
- 找不到最终会报错