JavaScript作用域和闭包,原理与用途?
JavaScript作用域和闭包,原理与用途
作用域
原理
作用域可以理解为变量和函数的“活动范围”。在 JavaScript 里,变量和函数并不是在任何地方都能被访问的,它们只能在特定的范围内起作用,这个范围就是作用域。JavaScript 中有全局作用域和函数作用域,ES6 还引入了块级作用域。
- 全局作用域:全局作用域是最外层的作用域,在全局作用域中声明的变量和函数可以在代码的任何地方被访问。就好像整个城市是一个全局作用域,城市里的公共设施(全局变量和函数)大家都能使用。
- 函数作用域:每个函数都有自己的作用域,在函数内部声明的变量和函数只能在该函数内部被访问,外部无法直接访问。这就好比每个家庭是一个函数作用域,家里的私有物品(函数内部的变量和函数)只有家庭成员(函数内部)能使用。
- 块级作用域:使用
let
和const
关键字在{}
块中声明的变量,只在该块内有效。例如if
语句、for
循环等的{}
内就是块级作用域。这类似于小区里的某一栋楼,楼里的设施(块级作用域内的变量)只有这栋楼的住户(块级作用域内)能使用。
用途
作用域的存在可以避免变量名冲突,提高代码的可维护性和安全性。不同作用域中的变量相互独立,不会相互干扰。
代码示例
// 全局作用域
var globalVar = '我是全局变量';
function testFunction() {
// 函数作用域
var functionVar = '我是函数内部变量';
console.log(globalVar); // 可以访问全局变量
console.log(functionVar); // 可以访问函数内部变量
}
testFunction();
console.log(globalVar); // 可以访问全局变量
// console.log(functionVar); // 报错,无法访问函数内部变量
if (true) {
// 块级作用域
let blockVar = '我是块级变量';
console.log(blockVar); // 可以访问块级变量
}
// console.log(blockVar); // 报错,无法访问块级变量
闭包
原理
闭包是指有权访问另一个函数作用域中变量的函数。简单来说,就是一个函数可以记住并访问它外部函数的变量,即使外部函数已经执行完毕。可以把闭包想象成一个“背包”,函数在执行时会把它需要的外部变量“装”进这个“背包”里,带着这个“背包”到处走,随时都能使用里面的变量。
用途
- 读取函数内部的变量:通过闭包可以在函数外部访问函数内部的变量。
- 让这些变量的值始终保持在内存中:闭包可以让函数内部的变量的值始终保持在内存中,不会随着函数执行完毕而被销毁。
代码示例
function outerFunction() {
var outerVar = '我是外部函数的变量';
function innerFunction() {
console.log(outerVar); // 访问外部函数的变量
}
return innerFunction;
}
var closure = outerFunction();
closure(); // 输出: 我是外部函数的变量
// 闭包让变量的值始终保持在内存中
function counter() {
var count = 0;
return function() {
return ++count;
};
}
var increment = counter();
console.log(increment()); // 输出: 1
console.log(increment()); // 输出: 2
在上面的代码中,innerFunction
就是一个闭包,它可以访问 outerFunction
中的 outerVar
变量。increment
也是一个闭包,它可以让 count
变量的值始终保持在内存中,每次调用 increment
函数时,count
的值都会加 1。