var a = 1;
if (true) {
console.log(a)//函数 函数提升
a = 2;
console.log(a)//2
function a() { }
a = 3
console.log(a)//3
}
console.log(a)//2 为什么???
var a = 1;
if (true) {
console.log(a)//函数 函数提升
a = 2;
console.log(a)//2
function a() { }
a = 3
console.log(a)//3
}
console.log(a)//2 为什么???
a = 3 // 这里是对if中的块级作用域的a赋值,所以不会影响外部的a
正如fefe
所说,在非严格模式下,结果是不可预测的。不同的浏览器和引擎对如何处理块中的函数声明实现了自己的规则。
为什么这个第四条 log 打印 2 呢
因为,根据规范函数声明是在当进入上下文时填入的; 同一周期,在进入上下文的时候还有一个变量声明“a”,变量声明在顺序上跟在函数声明和形式参数声明之后,而且在这个进入上下文阶段,变量声明不会干扰上下文中已经存在的同名函数声明或形式参数声明
上下文填充的顺序是: 函数的形参 -> 函数申明 -> 变量申明。
结论就是,你声明的 function a(){} 阻挡了下面的 a 赋值, 不会让 funciton 下面的赋值影响到最外层 a 的值
是因为你在 if 的作用域内声明了 函数
函数声明的实际规则如下:
函数声明只能出现在程序或函数体内。从句法上讲,它们 不能出现在Block(块)({ ... })中,例如不能出现在 if、while 或 for 语句中。因为 > Block(块) 中只能包含Statement语句, 而不能包含函数声明这样的源元素。另一方面,仔细看一看规则也会发现,唯一可能让表达式出现在Block> (块)中情形,就是让它作为表达式语句的一部分。但是,规范明确规定了表达式语句不能以关键字function开头。而这实际上就是说,函数表达> 式同样也不能出现在Statement语句或Block(块)中(因为Block(块)就是由Statement语句构成的)。
但这样写会有疑惑, 所以就有了块级作用域, 用人为标定的方式来划定变量的生效范围, 从而解决编写时的困惑, 就 let 和 const
如果
let a = 1;
if (true) {
console.log(a)//函数 函数提升
a = 2;
console.log(a)//2
function a() { }
a = 3
console.log(a)//3
}
console.log(a)//1 就变成了 1 , 那就是用 let 人为的划分了这个 a 的生效范围就在最外层声明的范围内 , 不会影响到 if 的块级作用域 , if 的块级作用域也不会影响到外面, 所以以后推荐用 let 来声明变量
看你问问题的时间也是搞到了好晚,在新手阶段,不要太深究这个细节,等你能静下心去看看红宝书 <<你真的懂 javascript? >>的这些原理书籍
这些自然就懂了, 这些在工作中遇不到的问题 如果一直深究,就会让你走近时间的深渊,无法自拔, 工作也做不好, 原理还没搞懂.
上面的总结也是从大叔的博客总结的 ,
如果还想深入了解,就看看这位
汤姆大叔的博客https://ock.cn/gkap7
var a = 1;
if (true) {
console.log(a)//1
a = 2;
console.log(a)//2
a = function () { }
console.log(a)//f(){}
a = 3
}
console.log(a);//3
结论是函数提升会导致块语句下的同名赋值无法映射到全局变量,可以使用表达式来替代
10 回答11.7k 阅读
2 回答3.2k 阅读✓ 已解决
2 回答4.2k 阅读✓ 已解决
3 回答2.7k 阅读✓ 已解决
3 回答1.8k 阅读✓ 已解决
2 回答1.7k 阅读✓ 已解决
4 回答2.5k 阅读✓ 已解决
conditionally created functions
由于历史的原因,块级函数定义的实现是非常混乱的。不同的环境的结果会很不同。至于为什么会出现某一个结果,也只能去咨询每一个具体环境(不过好像没啥地方咨询),或者看源码(如果有的话)。