作用域
作用域定义了变量和函数的可访问范围,决定了代码中变量和函数的可见性和生命周期。在 JavaScript 中,主要有两种类型的作用域:全局作用域与局部作用域,局部作用域又分为函数作用域和块级作用域(ES6出现之后)。
1. 全局作用域
全局作用域是最外层的作用域,在全局作用域中声明的变量和函数可以在代码的任何地方访问。如整个script标签或者是一个单独的js文件:
// 全局作用域
var globalVariable = 'I am a global variable';
function globalFunction() {
console.log(globalVariable); // 可以在函数内部访问全局变量
}
globalFunction(); // 输出: I am a global variable
console.log(globalVariable); // 可以在全局作用域中直接访问全局变量
2. 局部作用域
局部作用域又分为函数作用域和块级作用域
2.1 函数作用域
函数作用域是指在函数内部声明的变量和函数只能在该函数内部访问,外部无法直接访问。
function myFunction() {
var localVariable = 'I am a local variable';
console.log(localVariable); // 可以在函数内部访问局部变量
}
myFunction(); // 输出: I am a local variable
// console.log(localVariable); // 报错,localVariable 未定义,因为它在函数外部不可访问
2.2 块级作用域
ES6 引入了 let 和 const 关键字,它们可以创建块级作用域。块级作用域是指在 {} 内部声明的变量和函数只能在该块内部访问。
if (true) {
let blockVariable = 'I am a block variable';
console.log(blockVariable); // 可以在块内部访问块级变量
}
// console.log(blockVariable); // 报错,blockVariable 未定义,因为它在块外部不可访问
执行效率
全局变量存放在内存中,只有浏览器关闭时才会销毁,比较占内存资源;
而局部变量,当程序执行完毕后就会被销毁,比较节约内部资源。所以我们更喜欢使用局部变量。
作用域链
作用域链的底层是变量查找机制。
当访问一个变量时,JavaScript引擎会首先在当前作用域查找该变量,如果没有找到,就会沿着作用域链向上查找,直到全局作用域。如果在全局作用域中也没有找到,通常会抛出一个引用错误(ReferenceError)。
// 全局作用域
var globalVar = 'Global variable';
function outerFunction() {
var outerVar = 'Outer variable';
function innerFunction() {
var innerVar = 'Inner variable';
// 访问 innerVar,直接在当前作用域中找到
console.log(innerVar);
// 访问 outerVar,当前作用域中找不到,沿着作用域链向上查找,在 outerFunction 的作用域中找到
console.log(outerVar);
// 访问 globalVar,当前作用域和 outerFunction 的作用域中都找不到,继续沿着作用域链向上查找,在全局作用域中找到
console.log(globalVar);
}
innerFunction();
}
outerFunction();
在上述示例中,innerFunction 内部形成了一个作用域链,它包含了 innerFunction 的作用域、outerFunction 的作用域和全局作用域。当 innerFunction 访问变量时,会按照作用域链的顺序依次查找。
作用域链的存在使得 JavaScript 能够实现变量的嵌套访问和闭包等特性,同时也保证了变量的安全性和封装性。