MST

星途 面试题库

面试题:JavaScript 赋值操作符在函数作用域中的扩展应用

假设有如下代码:function test() { let a = 1; (function() { a += 1; })(); return a; } 请分析该代码的执行结果,如果报错请说明原因。同时说明如何修改代码使 `a` 能正确累加,并且阐述这里面涉及到的 JavaScript 赋值操作符在不同作用域下的规则及原理。
19.3万 热度难度
编程语言JavaScript

知识考点

AI 面试

面试题答案

一键面试
  1. 执行结果分析
    • 这段代码不会报错。在JavaScript中,内部函数可以访问外部函数的变量,这是闭包的特性。
    • 外部函数 test 定义了变量 a 并赋值为 1。内部函数通过闭包访问到了外部函数的变量 a,并对其进行了 a += 1 的操作,也就是 a = a + 1。最后外部函数 test 返回 a 的值。
    • 所以执行 test() 的结果是 2
  2. 代码修改以确保正确累加(假设要多次累加)
    • 如果想要多次调用 test 函数让 a 正确累加,可以将 a 定义为外部变量,例如:
    let a = 1;
    function test() {
        (function() {
            a += 1;
        })();
        return a;
    }
    
    • 这样每次调用 test 函数,a 都会基于上次的值进行累加。
  3. JavaScript赋值操作符在不同作用域下的规则及原理
    • 全局作用域:在全局作用域中定义变量并使用赋值操作符,变量属于全局对象(在浏览器环境中是 window,在Node.js环境中是 global)。例如 let globalVar = 10;,在浏览器中 window.globalVar 可以访问到该变量(注意 let 定义的变量在全局作用域下不会成为全局对象的属性,var 定义的变量会)。
    • 函数作用域:在函数内部使用赋值操作符定义变量,如果没有使用 letconst 等关键字,在非严格模式下会自动提升为全局变量(这是 var 的特性,letconst 不会提升)。例如:
    function scopeTest() {
        a = 5; // 没有使用let或const,在非严格模式下a会成为全局变量
        let b = 10; // b是函数作用域内的局部变量
    }
    
    • 块级作用域:ES6引入了块级作用域,由 {} 形成,使用 letconst 定义的变量在块级作用域内有效。例如:
    {
        let blockVar = 20;
        console.log(blockVar); // 20
    }
    console.log(blockVar); // 报错,blockVar超出了作用域
    
    • 闭包中的赋值操作:在闭包中,内部函数可以访问并修改外部函数作用域中的变量。因为内部函数持有对外部函数作用域的引用,所以外部函数执行完毕后,其作用域不会被垃圾回收机制回收,从而使得内部函数可以持续访问和修改外部函数作用域中的变量,就像题目中的代码一样。