js_预解析

预解析的讲解

首先知道什么是预解析?

答:提前解析代码。

预解析做什么事?

答:把变量和函数的声明提前(提前到当前所在的作用域的最上面)

输出函数的代码:

1
2
3
4
5
6
console.log(a);//输出函数的代码
function a(){
var num=20;
console.log(num);//20
}

预解析详细讲解

1
2
3
4
5
6
7
8
预解析中,变量的提升,只会在当前的作用域的最上面,
函数中的变量只会提前到函数的作用域的最前面,不会逃出函数.
预解析会分段(多对script标签中的函数重名,预解析的时候不会冲突)
js代码的执行是由浏览器的js解析器来执行的。
解析的时候分为两个过程:预解析过程和代码执行过程。
浏览器是软件,浏览器的下面的在系统上运行,系统在硬件上运行;
浏览器可以解析html、css、js

预解析的过程:

1、把变量的声明提升到作用域的最前面,只会提升声明,不会提升赋值;

2、把函数的声明提升到作用域的最前面,只提升声明,不会提升调用;

3、先提升var,再提升function

变量的声明提前的情况

1
2
3
4
5
6
7
8
console.log(num);//undefined,把变量的声明提前了
var num=10;
console.log(num);//10
//等价于下面的代码:
var num;
console.log(num);//undefined,把变量的声明提前了,但是没有赋值
num=10;
console.log(num);//10

函数的声明提前的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
function f1(){
console.log("你好啊");
}
f1();
function f1(){
console.log("你好坏哦啊");
}
f1();
//你好坏哦啊
//你好坏哦啊
//上面的代码等价于:
function f1(){
console.log("你好啊");
}
function f1(){
console.log("你好坏哦啊");
}
f1();
f1();
//你好坏哦啊
//你好坏哦啊

函数和变量的情况

1、

1
2
3
4
5
6
7
8
9
10
11
12
13
f1();
function f1(){
console.log(num);//undefined
var num=10;
}
//上面的代码等价于:
function f1(){
var num;
console.log(num);//undefined
num=10;
}
f1();

2、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f1();
var num=20;
function f1(){
console.log(num);//undefined
var num=10;
}
//上面的函数等价于:
var num;
function f1(){
var num;
console.log(num);//undefined,虽然在函数外部声明了num且赋值,但是并不影响函数内部的num,因为在函数内部已经重新声明了num。
num=10;
}
num=20;
f1();

3、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
f1();
var num=20;
function f1(){
console.log(num);//undefined
var num=10;
}
//代码等价于下面的:
//f1();调用函数,会把函数的声明提升到作用域的前面
var num;
function f1(){
console.log(num);//undefined
}
f1();//函数先调用,变量赋值在后面
num=20;//变量的声明也会提前

4、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
var num=20;
function f1(){
console.log(num);//20
//var num=10;
}
f1();//函数调用在下面,变量和函数声明在上面,变量声明且已经赋值,则console看到结果是num的值20
//上面的代码等价于:
var num;
function f1(){
console.log(num);//20
//var num=10;
}
num=20;
f1();

5、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
function f1(){
console.log(num);//undefined
//var num=10;
}
f1();
var num=20;//变量的声明会提前,但是提前的没有赋值,变量的赋值在这里,则console看到的是undefined
//上面的代码等价于
var num;
function f1(){
console.log(num);//undefined
//var num=10;
}
f1();
num=20;

预解析案例

1、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
function f1(){
console.log(num);//undefined
var num=10;//变量的声明提前到函数内部的最前面的,但是赋值不会提升
}
f1();
console.log(num);//报错
//上面代码等价于:
function f1(){
var num;//声明的是局部变量,函数外部访问不到
console.log(num);//undefined
num=10;//变量的声明提前到函数内部的最前面的,但是赋值不会提升
}
f1();
console.log(num);//报错

2、

1
2
3
4
5
6
7
8
9
10
f1();
function f1(){
console.log("哈哈");//这个会执行
}
//上面代码等价于
function f1(){
console.log("哈哈");//这个会执行
}
f1();

3、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var a=27;
function f1(){
alert(a);//undefined
var a=10;
}
f1();
console.log(a);//27
//上面代码等价于
var a;
function f1(){
var a;//这里的a和外面声明的a不一样
alert(a);//undefined
a=10;
}
a=27;
f1();
console.log(a);//27

4、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
function a(){
console.log(a);//
}
a();//调用函数之后,54行输出的仍然是函数的代码
var a=1;
console.log(a);//1
//函数和变量的声明都提前了
//上面的代码等价于
var a;
function a(){
console.log(a);//输出函数的代码
}
a();//调用函数之后,输出的仍然是函数的代码
a=1;
console.log(a);//1

5、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var a=19;
f1();
function f1(){
var b=9;
console.log(a);//undefined
console.log(b);//9
var a='123';
}
//上面的代码等价于
var a;
function f1(){
var b;
var a;
b=9;
console.log(a);//undefined
console.log(b);//9
a='123';
}
a=19;
f1();

6、注意

1
2
3
4
5
6
7
8
9
f1();//调用在函数的前面就不能调用--->报错,放在函数的后面可以调用-->undefined
var f1=function(){
console.log(a);
var a=10;
};//定义的匿名函数,是表达式;定义f1变量来接收函数的代码
//Uncaught TypeError: f1 is not a function
// at <anonymous>:1:1

7、

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
f2();
function f2(){
console.log(b);//undefined
var b=30;
}//定义的命名函数,调用放在函数的前面可以调用
//上面代码等价于
function f2(){
var b;
console.log(b);//undefined
b=30;
}
f2();
console.log(b);//报错