预解析
JavaScript 代码在浏览器中是由浏览器中的 JavaScript 解析器来执行的。JavaScript 解析器执行JavaScript代码的时候,分为两个过程:预解析过程和代码执行过程
预解析过程:
在当前的作用域下,JS 代码执行之前把通过 var
定义的变量和通过 function
声明的函数在内存中进行提前声明或者定义。
代码执行过程:
至上而下执行 JavaScript 代码
变量提升(预解析)
把变量的声明提升到当前作用域的最上面,提升的只是变量的声明,不会提升赋值。
示例:
// 在变量定义之前使用了变量
console.log(num); // undefined;变量定义了但没有赋值所以结果为 undefined,说明变量提升了
// 定义变量
var num = '变量预解析';
函数提升(预解析)
通过 function
定义的函数,会把函数的声明提升到当前作用域的最前面,只会提升函数的声明,不会提升调用。
// 在函数定义前进行调用
fun(); // 函数预解析;成功打印出了内容说明函数的声明被提升
function fun() {
console.log('函数预解析')
}
同级作用域中有多个同名函数
同级作用域中有多个同名函数时,预解析时后面的会覆盖前面的(就像变量的多次赋值)
f1(); // 函数预解析2
function f1(){
console.log("函数预解析1");
}
f1();// 函数预解析2
function f1(){
console.log("函数预解析2");
}
f1(); // 函数预解析2
函数名与变量名相同
同级作用域中,预解析时如果函数名与变量名相同,函数优先
// 打印结果为声明的函数
console.log(f2);
function f2(){
console.log('函数优先');
}
var f2 = '变量优先';
console.log(f2);// 变量优先;因为 f2 预解析后被再次赋值了
多对 script 标签中的函数名相同
若多对script标签中都有相同名字的函数,会分段进行预解析,函数之间互不影响
<script>
f1(); // 函数预解析1
function f1(){
console.log("函数预解析1");
}
</script>
<script>
f1(); // 函数预解析2
function f1(){
console.log("函数预解析2");
}
</script>
函数表达式声明函数的提升问题
通过函数表达式创建函数,会执行变量提升,只是提升了变量的声明其值为 undefined 还不是函数,所以无法被调用
func(); // 会报错
var func = function() {
console.log('能否调用');
}
先提升 funciton,再提升 var
JS 在进行预解析时,先提升函数声明,后提升变量,且函数声明会被提升到普通变量之前
既然先提升函数再提升变量为什么变量没有覆盖函数呢?这是因为变量在提升时只提升了变量的声明并没有提升变量的赋值