作用域以及作用域链
目录
1. 作用域
指变量存在的范围
1.1 es6 之前
种类 全局作用域和局部作用域
全局作用域
除函数大括号外都属于全局作用域
- 变量在整个程序中一直存在
- 定义在全作用域中的变量,任何地方都能访问
函数作用域(局部作用域)
定义函数时,在函数内部定义的变量就属于局部作用域
- 定义在函数内部的变量,只能在函数内部进行访问
function f1() {
var i = 9;
console.log("输出111:",i);
}
f1();
console.log("输出222:",i);
1.2 ES6之后
种类 全局作用域,局部作用域,块级作用域
全局作用域:
- 定义在全局作用域中的变量,任何地方都能访问
函数作用域
定义函数时,大括号里面的就是局部作用域
- 定义在局部作用域的变量,只能在局部作用域内访问
块级作用域
使用大括号中的代码片段都属于一个块,在大括号中定义的变量对外都是不可见的,称为块级作用域
- 定义在块级作用域的变量,只能在块级作用域内访问,在大括号外不能访问
{
let a = 999;
console.log("输出a的值111:", a);
}
console.log("输出a的值222:", a);
1.3 变量作用域
定义变量的方式(2 种):
- es6 以前:
var 变量名称
- es6 开始:
let 变量名称
两种定义方式区别
-
var 定义变量:
同一作用域内,var 定义的变量名能够重复
存在变量提升,能够先使用变量,再定义
-
let 定义变量
同一作用域内,let 定义的变量名能够重复
不存在变量提升,变量必须先定义,再使用
局部变量和全局变量
局部变量 在局部作用域内声明的变量,从定义那行开始,到大括号结束为止。
全局变量 在全局作用域内声明的变量,从定义那行开始,在整个程序中都能使用
- es6 后增加了块级作用域,在块级作用域中使用 let 声明的变量依然属于局部变量
- 在块级作用域中使用 var 声明的变量属于全局变量
无论在块级作用域还是函数作用域,省略 let 和 var 声明的变量默认属于全局变量
function f1() {
n = 3333;
}
f1(); //需要运行函数f1,才会在内存中存储函数,才能找到函数内的变量n
console.log("n=", n); // n=3333;
因为 n 没有属于 let 或者 var 定义,属于全局变量,所以能够在函数外访问到
1.4 函数作用域:变量只在函数内部存在
定义:
- 在函数内部定义的变量属于局部变量,在函数执行完毕,被垃圾回收机制回收。
- 在函数内部,能够读取函数外的全局变量,反之不行。
函数自身的作用域
函数自身也有作用域,函数的作用域是其声明时所在的作用域,不是其调用时所在的作用域。
function f1() {
var num = 111;
function f2() {
console.log("num=", num);
}
return f2;
}
var res= f1();
var num=222;
res();//111
因为函数f2定义在函数f1的内部,所以函数f2的作用域绑定在f1上,所以执行f1返回函数f2,
执行f2时,变量的取值会去函数f2所在的作用域即函数f1内部查找num,所以num取值时111
var num = 111;
function f2() {
console.log("num=", num);
}
function f1() {
var num = 222;
f2();
}
f1();// num=111
因为函数f2的作用域在函数f1的外层,所以函数f2中输出num值在f1的外层查找,所以num值=111,
不会取f1内的num值222
2.作用域链
当查找一个变量时,默认会在当前作用域范围查找;如果未找到,就会向父级进行查找;
如果到父级未找到,会继续向上级进行查找,直到找到全局作用域为止;如果找到全局作用域还是未找到,就报错。
- 在当前作用域查找到变量,就使用当前作用域的变量
function f1() {
var num = 111;
function f2() {
var num = 222;
console.log("num=", num);
}
f2();
}
f1(); //num=222
因为在函数 f2 内部存在变量 num,所以输出 f2 函数作用域内的 num=222;
- 当前作用域为找到,会去上级作用域查找
function f1() {
var num = 111;
function f2() {
console.log("num=", num);
}
f2();
}
f1(); //num=111
- 顺着作用域链,依次向上一级进行查找,直到找到全局作用域
var num = 999;
function f1() {
function f2() {
console.log("num=", num);
}
f2();
}
f1(); //num=999
- 如果找到全局作用域都未找到,就会报错
function f1() {
function f2() {
console.log("num=", num);
}
f2();
}
f1();
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?