JavaScript 变量作用域
在本教程中,您将了解决定变量可见性和可访问性的 JavaScript 变量作用域
在本教程中,您将了解决定变量可见性和可访问性的 JavaScript 变量作用域。
什么是变量作用域
作用域决定一个变量的可见性和可访问性。JavaScript 具有三个作用域:
- 全局作用域
- 本地作用域
- 块级作用域(从 ES6 开始)
全局作用域
当 JavaScript 引擎执行脚本时,它会创建一个全局执行上下文。此外,它还将您在函数外部声明的变量分配给全局执行上下文。这些变量在全局范围内。它们也称为全局变量。
例如下面的示例:
var message = 'Hi';message 变量是在全局作用域名的。它可以在脚本的任何地方访问。

本地作用域
您在函数内部声明的变量是函数的局部变量。它们被称为局部变量。例如:
var message = 'Hi';
function say() {
    var message = 'Hello';
    console.log(message);
}
say();
console.log(message);输出:
Hello
Hi当 JavaScript 引擎执行 say() 函数时,它会创建一个函数执行上下文。say() 函数内部声明的 message 变量绑定到函数的函数执行上下文,而不是全局执行上下文。

作用域链
考虑以下示例:
var message = 'Hi';
function say() {
    console.log(message);
}
say();输出:
Hi在这个例子中,我们引用 message 变量在 say() 函数内部。在幕后,JavaScript 执行以下操作:
- 在 say()函数的当前上下文(函数执行上下文)中查找变量message。它找不到message变量。
- 然后在外部的执行上下文中查找 message变量。最后 JavaScript 引擎在全局执行上下文找到message变量。
JavaScript 解析变量的方式是在其当前作用域查找变量,如果找不到该变量,则向上查找外部作用域,这称为作用域链。

多作用域链
考虑以下示例:
var y = 20;
function bar() {
    var y = 200;
    function baz() {  
        console.log(y);
    }
    baz();
}
bar();输出:
200在这个例子中:
- 首先,JavaScript 引擎在 baz()函数作用域查找变量y。但 JavaScript 它并没有找到变量y。所以 JavaScript 引擎向外部作用域查找变量y。
- 然后,JavaScript 引擎在 bar()函数找到变量y。它可以在bar()函数范围内找到变量y,因此 JavaScript 引擎停止搜索。
全局变量泄漏:JavaScript 的奇怪部分
请阅读下面的示例:
function getCounter() {
    counter = 10;
    return counter;
}
console.log(getCounter());输出:
10在此示例中,我们将 10 分配给不带 var, let 或 const 关键字的 counter 变量,然后将其返回。
在函数之外,我们调用 getCounter() 函数并在控制台中打印结果。这个问题被称为全局变量的泄漏。
在幕后,JavaScript 引擎首先在 getCounter() 函数的本地作用域内查找  counter 变量。
因为没有 var、let 或 const 关键字,所以 counter 变量在本地作用域内不可用。因为它尚未创建。
然后,JavaScript 引擎沿着作用域链在全局作用域中查找 counter 变量。全局作用域也没有 counter 变量,于是 JavaScript 引擎在全局范围内创建 counter 变量。
要修复这种奇怪的行为,您可以在脚本顶部或函数顶部使用 'use strict':
'use strict'
function getCounter() {
    counter = 10;
    return counter;
}
console.log(getCounter());现在,代码抛出一个错误:
ReferenceError: counter is not defined下面展示如何在函数中使用 'use strict':
function getCounter() {
    'use strict'
    counter = 10;
    return counter;
}
console.log(getCounter());块级作用域
ES6 提供 let 和 const 关键字,允许您在块范围内声明变量。
通常,只要你看到花括号 {},它就是一个块。它可以是 if ,  else , switch 条件或 for,  do while , 和 while 循环中的区域。
请参阅以下示例:
function say(message) {
    if(!message) {
        let greeting = 'Hello'; // 块级作用域
        console.log(greeting);
    }
    console.log(greeting); // ReferenceError
}
say();在此示例中,我们的 console.log(greeting) 引用在 if 创建的块级作用域的greeting 变量,导致错误 ReferenceError。
结论
在本教程中,您了解 JavaScript 变量作用域,包括函数作用域、全局作用域和块作用域。