var a = 0;
if (true) {
a = 1;
function a() {}
a = 21;
console.log(a);
}
console.log(a);
求两次 console 出来的值。
答案是21 1。
本菜鸡想了很久也没想明白第二个为啥是1。。
求大佬解惑 ?
var a = 0;
if (true) {
a = 1;
function a() {}
a = 21;
console.log(a);
}
console.log(a);
求两次 console 出来的值。
答案是21 1。
本菜鸡想了很久也没想明白第二个为啥是1。。
求大佬解惑 ?
面试官告诉你为什么了吗?
老实说我怀疑这是个未定义行为,反正我是没找到标准中关于这种情况的说明。
根据结果来分析一下,我觉得根源在于js没有为闭包准备一个关键字。
代码简化一下变成这样:
{
a = 1;
function a() {}
a = 21;
console.log(a);
}
代码块中有方法定义就会自动产生闭包, 因为有{}
的存在它又最多只会提升到这段代码块的最上面, a就变成了这段代码块中的局部变量。
a = 1
给"全局"变量 a 赋值
在方法定义之后的 a=21
其实是给局部变量赋值。
如果代码是这个样子我相信任何人都不会觉得难理解:
var a = 0;
{
a = 1;
var a_ = _closure() {};
a_ = 21;
}
附 v8 的bytecode, node版本:v14.7.0
function test() {
var a = 0;
{
a = 1;
function a() {}
a = 21;
// console.log(a);
}
// console.log(a);
}
test();
$ node --print-bytecode --print-bytecode-filter=test test.js
[generated bytecode for function: test (0x02368a073831 <SharedFunctionInfo test>)]
Parameter count 1
Register count 2
Frame size 16
29 S> 000002368A0743FE @ 0 : 0b LdaZero
000002368A0743FF @ 1 : 26 fb Star r0
29 E> 000002368A074401 @ 3 : 81 00 00 02 CreateClosure [0], [0], #2
000002368A074405 @ 7 : 26 fa Star r1
42 S> 000002368A074407 @ 9 : 0c 01 LdaSmi [1]
000002368A074409 @ 11 : 26 fa Star r1
69 S> 000002368A07440B @ 13 : 26 fb Star r0
75 S> 000002368A07440D @ 15 : 0c 15 LdaSmi [21]
000002368A07440F @ 17 : 26 fa Star r1
000002368A074411 @ 19 : 0d LdaUndefined
135 S> 000002368A074412 @ 20 : aa Return
Constant pool (size = 1)
Handler Table (size = 0)
Source Position Table (size = 15)
ECMAScript5标准里并没有描述“代码块里的函数声明”的行为,具体怎么执行要看引擎行为了,就上面的代码在Chrome和IE里执行结果就不同:
// IE
21
function a() {}
JSLint发现“语句块里声明函数”也会报错的,可以看看解释"Function declarations should not be placed in blocks"。
~出这样的面试题说明面试官比较虚
var a = 0 // 这里定义一个全局作用域变量a 并初始化为 0
if (true) { // 一个简单的if语句,制造一个简单的局部/词法作用域
a = 1 // js的奇怪设定 没有发现局部变量 那么修改的就是全局作用域的a
function a() { } // 声明一个局部变量a 此局部变量a在这一行是一个空函数
a = 21 // 受上一句影响,js以为 你修改的是新声明的 局部变量a
console.log(a) // 打印局部作用域的a (毕竟你已经声明了一个局部变量a)
} // 局部/词法作用域结束
console.log(a)// 打印全局作用域的a
如此解释,可?
我也同意微软的观点,面试官这样难为人真的好吗
8 回答4.7k 阅读✓ 已解决
6 回答3.4k 阅读✓ 已解决
5 回答2.8k 阅读✓ 已解决
6 回答2.3k 阅读
5 回答6.3k 阅读✓ 已解决
4 回答2.3k 阅读✓ 已解决
4 回答2.8k 阅读✓ 已解决
21 1 的输出结果不完全正确,在不同的浏览器下结果不同
在safari下结果为21 21
在chrome下结果为21 1
同时ECMAScript规范中说函数声明可以嵌套在条件语句块内,但是其运行的结果依赖于JS解析器的实现,其结果具有不确定性,不推荐在生产环境下使用