预解析
先来看几个例子
console.log(num);
//结果是多少?
//num is not defined
console.log(num); //结果是多少?
var num = 10;
//undefined
fn();
var fn = function() {
console.log('想不到吧');
}
JS运行代码的时候:
分为两步:
-
预解析:浏览器会默认把带有
var
和function
,放到当前作用域的最前面 -
代码执行:
按照代码的书写,从上往下执行
预解析:又分为变量预解析(变量提升) 和 函数预解析(函数提升)
- 变量预解析:把所有的
变量
提升到当前作用域
的最前面
,不
进行赋值
操作。
就拿上面的例子来说,例1
console.log(num);
var num = 10; //输出的结果是undefined
我们模拟一下,浏览器是怎么操作的
//提升变量
var num;
console.log(num); //在浏览器执行到这一步的时候,就已经开始报错啦。
num = 10;
再看一个例2
fn(); //报错
var fn = function() {
console.log('想不到吧');
}
道理和例1差不多,js事先提升变量,如下:
var fn;
fn(); //运行到这一步的时候,会发现居然没有fn(),所以就会报错啦。
fn = function() {
console.log('想不到吧');
}
- 函数预解析:把所有的
函数
提升到当前作用域
的最前面
,不调用函数
。
因此,不管下面这段代码钟的fn()
,放在哪个位置,都能够正常运行。
fn();
function fn() {
console.log('打印');
}
做几个小测试,看看你掌握了没有。
- 案例1
var num = 10;
fun();
function fun() {
console.log(num);
var num = 20;
}
相当于执行了以下步骤:
//先把所有的变量、函数提升到当前的作用域中,然后再依次执行代码
var num;
function fun() {
//函数内部也需要提升。
var num;
console.log(num); //报错,undefined
num = 20;
}
num = 10;
fun();
- 案例2
var num = 10;
function fn(){
console.log(num);
var num = 20;
console.log(num);
}
fn();
相当于执行下面步骤
var num;
function fn(){
var num;
console.log(num); //undefined
num = 20;
console.log(num); //20
}
num = 10;
fn();
- 案例3
var a = 18;
f1();
function f1() {
var b = 9;
console.log(a);
console.log(b);
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();
- 案例4
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);
}
相当于执行下面步骤
function f1() {
var a = b = c = 9;
//注意:var a =9; b =9 ;c = 9;这里是赋值操作,b和c直接赋值,相当于全局变量。
//tips:如果需要整体声明的话, var a =9 , b =9 ,c = 9;
console.log(a); //9
console.log(b); //9
console.log(c); //9
}
f1();
console.log(c); //9
console.log(b); //9
console.log(a); //a is not defined