JavaScript 预解析
1. 变量预解析 和 函数预解析
- js引擎运行js 分为两步: 预解析 代码执行
- 预解析 js引擎会把js 里面所有的 var 还有 function 提升到当前作用域的最前面
- 代码执行 按照代码书写的顺序从上往下执行
- 预解析分为 变量预解析(变量提升) 和 函数预解析(函数提升)
- 变量提升 就是把所有的变量声明提升到当前的作用域最前面 不提升赋值操作
- 函数提升 就是把所有的函数声明提升到当前作用域的最前面 不调用函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>预解析</title>
<script>
// (1)
// console.log(num); // 报错:Uncaught ReferenceError: num is not defined
// (2)
console.log(num); // undefined 为什么?
var num = 10;
// 因为先进行预解析 再进行代码执行
// 相当于执行了以下代码
// var num; // 先变量预解析(变量提升)
// console.log(num); // 代码执行,因为没赋值,所以是 undefined
// num = 10; // 再进行赋值 =10
// (3)
fn1();
function fn1() { // 函数提升
console.log(11);
}
function fn2() { // 函数提升
console.log(22);
}
fn2();
// 因为预解析的函数提升,函数声明提升到当前作用域的最前面,
// 所以函数调用放在 函数声明 前面还是后面都可以
// (4)
// fun(); // 报错 为什么?
// var fun = function () {
// console.log(33);
// }
// 函数表达式 调用必须写在函数表达式的下面
//
// 先进行预解析 再进行代码执行
// 相当于执行了以下代码
// var fun; // 变量提升 - 声明变量 fun 没有赋值
// fun(); // 代码执行 - 因为没有这个 fun 函数,但是调用 fun() 函数,所以会报错
// fun = function () {
// console.log(33);
// }
//
var fun = function () {
console.log(33);
}
fun();
</script>
</head>
<body>
</body>
</html>
2. 预解析案例
2.1 案例 1
代码运行结果是什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>案例 1</title>
<script>
var num = 10;
fun();
function fun() {
console.log(num); // undefined
var num = 20;
}
// 相当于执行了以下操作
// var num;
// function fun() {
// var num;
// console.log(num); // 就近原则,因为函数里的 num 没有赋值,所以是 undefined
// num = 20;
// }
// num = 10;
// fun();
</script>
</head>
<body>
</body>
</html>
2.2 案例 2
代码运行结果是什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>案例 2</title>
<script>
var num = 10;
function fn() {
console.log(num); // undefined
var num = 20;
console.log(num); // 20
}
fn();
// 相当于以下代码
// var num;
// function fn() {
// var num;
// console.log(num); // 就近原则,undefined
// num = 20;
// console.log(num); // 20
// }
// num = 10;
// fn();
</script>
</head>
<body>
</body>
</html>
2.3 案例 3
代码运行结果是什么?
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>案例 3</title>
<script>
var a = 18;
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 = 18;
// f1();
</script>
</head>
<body>
</body>
</html>
2.4 案例 4
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>案例 4</title>
<script>
f1();
console.log(c); // 9
console.log(b); // 9
console.log(a); // Uncaught ReferenceError: a is not defined
function f1() {
var a = b = c = 9;
console.log(a); // 9
console.log(b); // 9
console.log(c); // 9
}
// 以下代码
// function f1() {
// var a;
// a = b = c = 9;
// // 相当于 var a = 9; b = 9; c = 9;
// // b 和 c 直接赋值 没有 var 声明 当 全局变量看
// // 集体声明 var a = 9, b = 9, c = 9;
// console.log(a);
// console.log(b);
// console.log(c);
// }
// f1();
// console.log(c);
// console.log(b);
// console.log(a);
</script>
</head>
<body>
</body>
</html>
GitHub代码
gitee代码