JavaScript 作用域

在学习 JavaScript 时,作用域是一个非常重要的概念。作用域决定了变量和函数的可访问范围,也就是说在代码的哪些部分可以使用某个变量或函数。了解作用域可以帮助我们编写更清晰、更可靠的代码。
全局作用域
全局作用域是最外层的作用域,所有不在其他作用域内的变量和函数都属于全局作用域。在浏览器中,全局作用域通常是指 window 对象。
// 全局作用域
var globalVariable = 'I am a global variable';
function globalFunction() {
console.log('I am a global function');
}
console.log(window.globalVariable); // 输出:I am a global variable
globalFunction(); // 输出:I am a global function
在全局作用域中声明的变量和函数可以在任何地方被访问,但这也可能导致命名冲突和意外修改全局变量。
函数作用域
在 JavaScript 中,变量的作用域是通过函数来划分的,每个函数都有自己的作用域。在函数内声明的变量只在该函数内部可见,这被称为函数作用域。
function foo() {
var functionVariable = 'I am a function variable';
console.log(functionVariable); // 输出:I am a function variable
}
// console.log(functionVariable); // 报错:functionVariable is not defined
在上面的示例中,functionVariable 只能在 foo 函数内部被访问,外部无法访问它。
块级作用域
在 ES6 (ECMAScript 2015) 中引入了 let 和 const 关键字,可以用来创建块级作用域。块级作用域由花括号 {} 包围的代码块定义,其中声明的变量只在该代码块内部可见。
{
let blockVariable = 'I am a block variable';
const PI = 3.14159;
console.log(blockVariable); // 输出:I am a block variable
}
// console.log(blockVariable); // 报错:blockVariable is not defined
在上面的示例中,blockVariable 和 PI 只能在花括号内部被访问,在外部无法访问它们。
作用域链
当在一个作用域中访问变量时,JavaScript 引擎会沿着作用域链查找该变量。作用域链是指函数嵌套的层级关系,如果当前作用域无法找到变量,引擎会向上查找直到全局作用域。
var outerVariable = 'I am an outer variable';
function outerFunction() {
var innerVariable = 'I am an inner variable';
function innerFunction() {
console.log(outerVariable); // 输出:I am an outer variable
console.log(innerVariable); // 输出:I am an inner variable
}
innerFunction();
}
outerFunction();
在上面的示例中,innerFunction 内部可以访问到外部函数的变量 outerVariable 和内部函数的变量 innerVariable。
闭包
闭包是指可以访问其包含作用域中变量的函数,即使该函数在包含作用域外部被调用。闭包可以帮助我们在函数外部访问函数内部的变量,从而实现一些特殊的操作。
function createCounter() {
let count = 0;
return function() {
count++;
return count;
};
}
const counter = createCounter();
console.log(counter()); // 输出:1
console.log(counter()); // 输出:2
console.log(counter()); // 输出:3
在上面的示例中,createCounter 函数返回了一个内部函数,可以在外部访问并修改 count 变量,从而实现一个计数器。
总结
作用域是 JavaScript 中一个非常重要的概念,它决定了变量和函数的可访问范围。全局作用域包含了所有不在函数内部声明的变量和函数,函数作用域通过函数来划分,块级作用域通过 let 和 const 关键字创建,作用域链决定了变量的查找顺序,闭包可以访问包含作用域中的变量。
极客笔记