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