前言
想必大家在学习js的时候肯定也多少被作用域给烦恼过,那么今天让我来以一个言简意赅的方式让大家彻底读懂js中的作用域,从此作用域不再是问题。
三大作用域
首先我们要知道js中有全局作用域,块级作用域,函数作用域三大作用域。
全局作用域
全局作用域指的是在整个 JavaScript 程序中都可以访问的作用域,其中定义的变量可以在程序的任何地方被访问和修改。在全局作用域中定义的变量在程序的任何地方都可以被访问,包括函数内部和外部。这些变量通常被称为全局变量。全局作用域的变量可以在整个程序执行期间保持其值,并且可以被任何函数调用。因此,全局作用域对于共享数据和信息在整个程序中起到了重要作用。
let globalVar = 100;
function globalScopeExample() {
console.log(globalVar); // 输出:100
}
globalScopeExample();
console.log(globalVar); // 输出:100
在这个例子中,变量 globalVar
是在全局作用域中定义的,在函数内部和函数外部都可以访问到。
function anotherGlobalScopeExample() {
console.log(globalVar); // 输出:100
}
anotherGlobalScopeExample();
这个例子展示了即使在另一个函数中,仍然可以访问到全局作用域中定义的变量 globalVar
。
// 全局作用域中修改变量
globalVar = 200;
function modifiedGlobalScopeExample() {
console.log(globalVar); // 输出:200
}
modifiedGlobalScopeExample();
console.log(globalVar); // 输出:200
这个例子演示了如何在全局作用域内修改全局变量,并且在函数内外都可以访问到这个修改后的值。
块级作用域
块级作用域是指在 JavaScript 中由一对花括号 {}
包裹起来的代码块所形成的作用域范围。在块级作用域中,通过关键字 let
或 const
声明的变量仅在该代码块内部可见和访问,外部无法访问。这种作用域范围的引入使得变量的作用域更加局限,有利于避免变量污染和命名冲突。块级作用域也使得在不同的代码块中可以定义相同名字的变量而不会发生冲突,因为它们处于不同的作用域内。在 ES6 之前,JavaScript 中没有块级作用域,而是采用函数作用域和全局作用域。引入块级作用域的概念可以更细粒度地控制变量的作用范围,提高了代码的可读性和可维护性。
function blockScopeExample() {
if (true) {
let x = 10;
console.log(x); // 输出:10
}
// console.log(x); // 这里会导致 ReferenceError,因为 x 在这里不可见
}
blockScopeExample();
在这个例子中,变量 x
是在 if
语句的代码块中定义的,因此它只在该代码块内可见。
function anotherBlockScopeExample() {
{
let y = 20;
console.log(y); // 输出:20
}
// console.log(y); // 这里会导致 ReferenceError,因为 y 在这里不可见
}
anotherBlockScopeExample();
这个例子展示了在不同的代码块中可以定义相同名字的变量而不会发生冲突,因为它们处于不同的块级作用域内。
// 块级作用域中修改变量
{
let z = 30;
console.log(z); // 输出:30
z = 40; // 修改变量值
console.log(z); // 输出:40
}
这个例子演示了在块级作用域内部可以修改块级作用域中定义的变量,并且这些修改只在当前作用域内有效。
函数作用域
函数作用域是指在 JavaScript 中函数内部定义的变量仅在该函数内部可见和访问的作用域范围。在函数内部定义的变量称为局部变量,它们只能在所属函数内部使用,而在函数外部是无法访问它们的。这种作用域可以帮助保护变量不被意外修改或泄露到全局作用域中,同时也提供了一种封装数据和逻辑的方式,使得代码更具可维护性和可读性。函数作用域允许在不同函数中使用相同名称的变量而不会产生冲突,并且在函数调用结束后,函数作用域中的变量会被销毁,释放内存空间,这有助于避免内存泄漏问题。
function functionScopeExample() {
let y = 50;
console.log(y); // 输出:50
}
functionScopeExample();
// console.log(y); // 这里会导致 ReferenceError,因为 y 在这里不可见
在这个例子中,变量 y
是在函数 functionScopeExample
内部定义的,因此它只在该函数内部可见。
function anotherFunctionScopeExample() {
let z = 60;
console.log(z); // 输出:60
}
anotherFunctionScopeExample();
这个例子展示了即使在另一个函数中,也不能访问另一个函数内部定义的变量 z
,因为它们都处于不同的函数作用域内。
// 函数作用域中修改变量
functionScopeExample();
functionScopeExample(); // 调用两次以验证是否会影响
function functionScopeExample() {
let y = 70;
console.log(y); // 输出:70
y = 80; // 修改变量值
console.log(y); // 输出:80
}
这个例子演示了在函数作用域内部可以修改函数作用域中定义的变量,并且这些修改只在当前作用域内有效。
例子
接下来,我们举一些具体的例子说明它们之间的区别与联系
- 全局作用域:
let globalVar = 50;
function globalScopeExample() {
console.log(globalVar); // 输出:50
}
globalScopeExample();
console.log(globalVar); // 输出:50
- 全局作用域修改变量:
globalVar = 100;
function modifiedGlobalScopeExample() {
console.log(globalVar); // 输出:100
}
modifiedGlobalScopeExample();
console.log(globalVar); // 输出:100
- 函数作用域:
function functionScopeExample() {
let localVar = 20;
console.log(localVar); // 输出:20
}
functionScopeExample();
// console.log(localVar); // 这里会导致 ReferenceError,因为 localVar 在函数外不可见
- 函数作用域修改变量:
functionScopeExample();
function functionScopeExample() {
let localVar = 30;
console.log(localVar); // 输出:30
localVar = 40; // 修改变量值
console.log(localVar); // 输出:40
}
- 块级作用域:
if (true) {
let blockVar = 60;
console.log(blockVar); // 输出:60
}
// console.log(blockVar); // 这里会导致 ReferenceError,因为 blockVar 在块级作用域外不可见
- 块级作用域修改变量:
{
let blockVar = 70;
console.log(blockVar); // 输出:70
blockVar = 80; // 修改变量值
console.log(blockVar); // 输出:80
}
- 全局作用域变量在函数内部访问:
let globalVar = 90;
function accessGlobalVar() {
console.log(globalVar); // 输出:90
}
accessGlobalVar();
- 函数作用域变量在函数外部无法访问:
function accessLocalVar() {
let localVar = 110;
}
accessLocalVar();
// console.log(localVar); // 这里会导致 ReferenceError,因为 localVar 在函数外不可见
- 块级作用域变量在块级作用域外部无法访问:
{
let blockVar = 120;
}
// console.log(blockVar); // 这里会导致 ReferenceError,因为 blockVar 在块级作用域外不可见
- 同名变量在不同作用域中不会冲突:
let x = 130;
function outerScope() {
let x = 140;
console.log(x); // 输出:140
}
outerScope();
console.log(x); // 输出:130
总结
它们有以下区别:
全局作用域:
- 全局作用域是指在代码中任何地方都可访问的变量和函数。
- 在全局作用域中声明的变量和函数可以在程序的任何地方使用。
- 全局作用域中声明的变量和函数在整个程序执行期间都存在。
函数作用域:
- 函数作用域是指在函数内部声明的变量和函数只能在函数内部访问。
- 在函数外部无法直接访问函数内部的变量和函数,这些变量和函数只在函数执行期间存在。
- 函数作用域允许在不同函数中使用相同的变量名而不会相互干扰。
块级作用域:
- 块级作用域是指在花括号
{}
内声明的变量,例如在if
语句、for
循环或{}
代码块中声明的变量。 - 在块级作用域内声明的变量只能在该块级作用域内访问,外部代码无法访问块级作用域内的变量。
- 块级作用域有助于避免变量泄漏和命名冲突,并且提高了代码的可读性和可维护性。
- 块级作用域是指在花括号
综上所述,全局作用域允许在整个程序中访问变量和函数,函数作用域限制了变量和函数的访问范围在函数内部,而块级作用域则进一步细分了作用域,使得变量在更小的范围内可见。