发布于 2026-01-06 7 阅读
0

JavaScript 作用域

JavaScript 作用域

根据 MDN 的定义,JavaScript 中的“作用域”是指代码的当前执行上下文。这究竟是什么意思呢?作用域定义了当前可访问的变量和值,它也可以指变量的环境。让我们直接来看一个例子:

function hello(){
    var phrase = "Hello";
    console.log(phrase + " Dylan");
}

console.log(phrase);
Enter fullscreen mode Exit fullscreen mode

我们有一个名为 hello() 的函数,并在函数内部定义了一个名为“phrase”的变量。如果我们尝试从函数外部访问变量“phrase”,将会收到以下错误:

Uncaught ReferenceError: phrase is not defined
Enter fullscreen mode Exit fullscreen mode

这很容易理解,对吧?从全球视角来看,我们并不知道什么是“短语”。

但是,如果我们定义一个全局变量,并尝试在函数内部使用它:

var person = "Dylan"

function hello(){
    var phrase = "Hello";
    console.log(phrase + " "+ person);
}

hello()
Enter fullscreen mode Exit fullscreen mode

我们将得到:

Hello Dylan
Enter fullscreen mode Exit fullscreen mode

由此可知,作用域遵循层级结构,子层可以访问父层的变量,但反过来不行。

在上一篇文章(JavaScript:单线程但非阻塞)中,我们提到 JavaScript 引擎拥有函数执行上下文的调用栈。全局执行上下文创建时,也会引入全局变量环境。如果我们现在定义一个全局变量,该变量将被添加到全局对象(例如浏览器中的 window 对象)下。

图片描述

每个执行上下文都有一个局部变量环境,称为局部作用域。如果我们尝试访问当前执行上下文中的一个变量,它会首先在局部作用域中查找该变量。如果找不到该变量,它会向上追溯到父作用域查找。这被称为作用域链。例如:

function func1(){
    var a = 20;
    return function func2(){
        console.log(a);
    }
}

var a = 10;

func1()();
Enter fullscreen mode Exit fullscreen mode

在这个例子中,代码试图查找变量a,因为它在 func2 中使用。在 func2 的作用域内找不到 a 后,它会向上查找 func1 并找到了它(a = 20)。因此,控制台输出的结果为 20。

执行上下文的作用域链

图片描述

如果我们把代码改成这样:

function func1(){
    var a = 20;
    return func2()
}

function func2(){
    console.log(a);
};

var a = 10;

func1()
Enter fullscreen mode Exit fullscreen mode

这次输出的是 10。这是为什么呢?我们需要引入另一个术语:词法作用域。词法作用域指的是函数定义的位置,而不是调用的位置。在第一个例子中,函数 func2 定义在 func1 内部,因此它会向上查找 func1 中缺失的变量,因为该变量不在其当前作用域内。然而,在第二个例子中,函数 func2 定义在全局作用域内(与 func1 处于同一级别),因此它会向上查找全局作用域来获取缺失的变量。

希望这篇文章能让你对 JavaScript 的作用域机制有个大致的了解。在以后的文章中,我还会介绍诸如提升、闭包、块级作用域等概念,以便让你更清楚地理解(本来应该在这篇文章里讲到的,但我太忙了,抱歉)。

请关注我,我会持续发布关于网页设计、编程和自我提升的文章😊

在 Medium 上关注我

文章来源:https://dev.to/ohdylan/javascript-scoping-3adl