跳转到主要内容
myfreax
返回

JavaScript 变量作用域

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 变量作用域,包括函数作用域、全局作用域和块作用域。

myfreax

  1. 暂无评论,快来抢沙发吧!