作用域
作用域(scope)规定了变量能够访问的“范围”,离开这个“范围”变量就不能够被访问。
作用域被分为:局部作用域和全局作用域。
局部作用域
局部作用域分为函数作用域和块作用域
1.函数作用域
在函数内部声明的变量只能在函数内部访问,外部无法直接访问。
function getNumber(){
// 函数内部是函数作用域 属于局部变量
let num = 10;
}
// Uncaught ReferenceError: num is not defined 此处报错 函数外部无法使用局部作用域变量
console.log(num)
总结:
- 函数内部声明得变量,在函数外部不能被访问。
- 函数的参数也是函数内部的局部变量(形参)。
- 不同函数内部声明的变量不能互相访问。
- 函数执行完毕后,函数内部的变量被清空了。
2.块作用域
在JavaScript中使用{}包裹的代码称为代码块,代码块内部声明的变量外部将【有可能】无法被访问。
// 案例 1
for(let i=1;t<=6;t++){
// t 只能在该代码中被访问
console.log(t) // 正常输出
}
// 超出了 t 的作用域
console.log(t) // 报错
// 案例 2
if(true){
let j = 10
}
console.log(j) // 报错 let会生成块级作用域
- let 声明的变量会产生块级作用域。
- var 声明的变量不会产生块级作用域。
- const 声明的常量会产生块级作用域
- 不同代码之间的变量无法相互访问。
- 推荐使用 let 或 const。
全局作用域
<script>标签和.js文件的【最外层】就是所谓的全局作用域,在这些部位声明的变量在任何作用域都可以使用。
<script>
// 全局作用域
const num = 10
function fn(){
// 函数内部可以使用全局作用域的变量
console.log(num)
}
// 此处为全局作用域
</script>
注意:
- 为window对象动态添加的属性默认也是全局属性。
- 函数中未使用任何关键字声明的变量为全局变量,不推荐。
- 尽可能少的声明全局变量,防止全局变量被污染。
作用域链
思考:
<script>
// 全局作用域
let a = 1;
let b = 2;
// 局部作用域
function f(){
let a = 1;
// 局部作用域
function g(){
a = 2;
console.log(a)
}
g()
}
f()
</script>
输出:2
作用域链本质上是底层的变量查找机制。
- 当函数被执行时,会优先查找当前函数作用域中查找变量。
- 如果当前作用域查找不到则会一次逐级查找父级作用域直到全局作用域。
总结:
- 嵌套关系的作用域串联起来形成了作用域链。
- 相同作用域链中按照从近到远的规则查找变量。
- 子作用域能够访问父作用域,父级作用域无法访问子级作用域。