面试题答案
一键面试- 使用
var
时的分析:- 变量作用域和提升机制:
- 在JavaScript中,
var
声明的变量存在函数作用域,并且会发生变量提升。这意味着变量的声明会被提升到函数的顶部,但初始化(赋值)不会提升。 - 在函数
A
中,var a = 'A1';
变量a
会提升到函数A
的顶部,初始值为undefined
,然后再赋值为A1
。 - 在函数
B
中,var a = 'B1';
变量a
同样提升到函数B
的顶部,初始值为undefined
,然后再赋值为B1
。这里的a
和函数A
中的a
是不同的变量,因为B
函数有自己的函数作用域。 - 在函数
C
中,a = 'C1';
这里操作的a
是函数B
中的a
,因为C
函数作用域内没有声明自己的a
,会沿着作用域链向上查找,找到函数B
中的a
。
- 在JavaScript中,
- 每次
console.log
输出的值:- 当执行
A()
时,进入函数A
,a
被初始化为A1
。然后调用B()
:- 进入函数
B
,a
提升为undefined
,第一个console.log(a);
输出undefined
,因为此时a
虽然声明提升,但还未赋值。 - 接着
a
被赋值为B1
,第二个console.log(a);
输出B1
。 - 调用
C()
,在C
中a
是函数B
中的a
,此时a
为B1
,所以第三个console.log(a);
输出B1
。 - 然后
a
被赋值为C1
,第四个console.log(a);
输出C1
。 C()
执行完毕,回到B()
,第五个console.log(a);
输出C1
,因为a
在C
中已经被修改为C1
。B()
执行完毕,回到A()
,第六个console.log(a);
输出A1
,因为这里操作的是函数A
中的a
,函数B
中的操作不会影响到它。
- 进入函数
- 当执行
- 变量作用域和提升机制:
- 将
var
全部替换为let
时的分析:- 变量作用域和提升机制:
let
声明的变量存在块级作用域,并且不存在变量提升。它会形成暂时性死区(TDZ),在变量声明之前访问该变量会抛出ReferenceError
。- 在函数
A
中,let a = 'A1';
变量a
有函数A
的块级作用域。 - 在函数
B
中,let a = 'B1';
变量a
有函数B
的块级作用域,和函数A
中的a
是不同的变量。 - 在函数
C
中,由于C
函数作用域内没有声明自己的a
,会沿着作用域链向上查找,找到函数B
中的a
。
- 执行结果变化:
- 当执行
A()
时,进入函数A
,a
被初始化为A1
。然后调用B()
:- 进入函数
B
,由于let
没有变量提升且存在暂时性死区,第一个console.log(a);
会抛出ReferenceError
,因为在声明let a = 'B1';
之前访问了a
。后续代码不会再执行。
- 进入函数
- 当执行
- 变量作用域和提升机制:
所以,使用var
和let
在作用域和执行结果上有明显的不同。使用var
可能因为变量提升导致一些不易察觉的问题,而let
通过块级作用域和暂时性死区提供了更严格的变量作用域规则。