一、预解析是什么?
预解析:就是提前解析代码。
JS代码的执行是由浏览器中的JS解析器(可以理解为浏览器)来执行的。JS解析器执行JS代码的时候,分为两个过程:预解析过程和代码执行过程
//关于变量的预解析
// 没有声明变量,直接输出会报错
console.log(num);
var num;
// 声明变量,没有赋值,此时这个变量的值为undefined
console.log(num);
// 声明并数值num,在输出num的下方
// 正常情况下应该报错,但是此时结果为undefined
console.log(num);
var num = 10;
// 所以我们认为它被浏览器读取的顺序应该是这样的
var num;
console.log(num);
num = 10;
// 浏览器把num的声明提前了,但是赋值没有被提前
//关于函数的预解析
// 正常情况下函数是先声明在调用,没有声明的调用会报错
f1(); //函数的调用
function f1() {
console.log("函数的声明");
}
// 此时运行代码后,正常输出
// 说明此时浏览器将函数的声明提前了,运行顺序如下
function f1() {
console.log("函数的声明");
}
f1(); //函数的调用
二、预解析做了什么事?
把变量的声明提前了,不提前赋值——提前到当前所在作用域的最上面
把函数的声明提前了,不提前调用——提前到当前所在作用域的最上面
例如:你能算出num的输出结果为什么吗?
f1();//函数的调用
var num = 20;
function f1() {
console.log(num);
}
三、预解析分段问题的局部作用域的问题
1.预解析在变量的提升中,只会在当前的作用域中提升,提前到当前的作用域的最上面;函数中的变量只会提前到函数的作用域中的最前面,不会出去
function f1() {
console.log(num);
var num = 10;
}
f1();
console.log(num);
2.预解析会分段(多对的script标签中函数重名,预解析的时候不会冲突)
<script>
f1();
function f1() {
console.log("hh");
}
</script>
<script>
f1();
function f1() {
console.log("oo");
}
</script>
//输出hh和oo
四、快速识别预解析的结果
1.变量在函数内部被提前
//例题:看看以下代码弹框和控制台输出的分布是什么
var a = 25;
function abc() {
alert(a);
var a = 10;
}
abc();
console.log(a);
运行结果:
2.在当前作用域下,JS代码执行之前,浏览器会默认把带有var和function声明的变量在内存中进行提前声明或者定义
//例题:看看以下代码控制台输出的分布是什么
console.log(a);
function a() {
console.log('aaa');
}
var a = 1;
console.log(a);
运行结果:
3.注意变量的使用范围
//例题:看看以下代码控制台输出的分布是什么
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
var a = b = c = 9;
console.log(a);
console.log(b);
console.log(c);
}
运行结果:
4.匿名函数解析
//例题:看看以下代码控制台输出的分布是什么
f1();
var f1 = function() {
console.log(a);
var a = 10;
}
运行结果: