MST

星途 面试题库

面试题:JavaScript在Web编程中作用域链相关问题

请阐述JavaScript在Web编程中作用域链的工作原理,并举例说明如何通过作用域链访问变量。如果在函数内部有同名变量在不同作用域中定义,访问规则是怎样的?
18.5万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试

作用域链工作原理

  1. 定义:作用域链是JavaScript中用于解析变量和函数标识符的一种机制。它由多个执行上下文的变量对象(VO)或活动对象(AO,函数执行时的VO)组成的链式结构。
  2. 形成过程:当代码执行进入一个执行上下文(全局上下文或函数上下文)时,会创建一个变量对象,这个对象包含了该上下文中定义的变量和函数声明。如果当前上下文是函数上下文,还会创建arguments对象。然后,当前上下文的作用域链会被初始化为包含该变量对象(活动对象)和外部(父)上下文的作用域链。
  3. 查找变量:当JavaScript引擎需要解析一个变量名时,它会从当前执行上下文的作用域链的前端(即当前上下文的变量对象)开始查找。如果找到了该变量名对应的属性,就返回该属性的值;如果没有找到,就会沿着作用域链向上查找,直到找到该变量或者到达全局上下文(全局上下文的变量对象查找完毕后,如果还没找到,就返回undefined)。

举例说明通过作用域链访问变量

var globalVar = 'global value';

function outer() {
    var outerVar = 'outer value';

    function inner() {
        var innerVar = 'inner value';
        console.log(globalVar); // 通过作用域链访问全局变量 globalVar
        console.log(outerVar); // 通过作用域链访问外部函数的变量 outerVar
        console.log(innerVar); // 访问自身函数的变量 innerVar
    }

    inner();
}

outer();

在上述代码中,inner函数内部通过作用域链依次访问了全局变量globalVar、外部函数outer的变量outerVar以及自身的变量innerVar

函数内部同名变量不同作用域的访问规则

  1. 优先访问局部变量:如果在函数内部有一个变量和外部作用域中的变量同名,函数内部会优先访问局部变量。例如:
var num = 10;

function test() {
    var num = 20;
    console.log(num); // 输出 20,优先访问函数内部的局部变量 num
}

test();
  1. 访问外部同名变量:如果要访问外部作用域中的同名变量,可以使用闭包或window对象(在浏览器环境下,全局变量是window对象的属性)。例如,使用闭包的方式:
var num = 10;

function outer() {
    var num = 20;

    function inner() {
        console.log(num); // 输出 20,优先访问 outer 函数的局部变量 num

        function subInner() {
            console.log(num); // 输出 20,优先访问 outer 函数的局部变量 num

            function subSubInner() {
                var num = 30;
                console.log(num); // 输出 30,优先访问 subSubInner 函数的局部变量 num

                function accessOuter() {
                    // 使用闭包访问外部作用域(outer 函数)的 num 变量
                    var outerNum = num;
                    return outerNum;
                }
                console.log(accessOuter()); // 输出 30,这里访问的是 subSubInner 函数内的 num
            }
            subSubInner();
        }
        subInner();
    }
    inner();
}

outer();

如果在浏览器环境下,要访问全局同名变量,可以通过window对象:

var num = 10;

function test() {
    var num = 20;
    console.log(window.num); // 输出 10,通过 window 对象访问全局变量 num
}

test();