先聊聊什么是预解析
预解析指的就是函数的编译和执行的过程,js是一个解释型的语言,就是在代码执行之前,先对代码进行通读和解释,然后再执行代码。也就是说js运行前会有两个步骤:
#1:解释代码:
因为是在所有代码执行之前进行解释,所以叫做预解析(预解释)。
预解析的内容有两个:
a:声明式函数
1):声明式函数,指的是function f1() {
要执行的代码;
}
仅仅是声明式函数,像赋值式函数就不属于要预解析的内容了。
(什么是赋值式函数?简单说一下就是指用var 一个变量等于一个函数的方法创建的一个函数:var f1= function () {要执行的代码;})
b:var关键字
在内存中声明有一个变量名。
#2:然后才是执行代码。
举几个栗子
例1:
fn();//'我是fn函数'
console.log(num);//undefined
function fn(){
console.log('我是fn函数')
}
var num = 100;
咱们来看看这一段简单代码是要怎么解析的:
根据咱们上面所说:先找出声明式函数和var关键字命名的变量,然后将之提前至最前面,然后再是执行代码。
//第一阶段预解析:将下面代码提至最前面
function fn(){
console.log('我是fn函数')
}
var num ;
//第二阶段代码执行:
fn();//'我是fn函数'
console.log(num);//undefined
num = 100;//这里才会赋值
//按照这个顺序运行下来
*这里有个点要注意下:
我们的var关键字在预解析阶段只是声明变量,而不进行赋值,赋值是在第二阶段代码执行时才会进行赋值。因此是将声明式函数和声明变量提前至代码运行的最前面。
综合一二阶段按顺序执行我们可以看到:
先是声明了一个fn的函数,然后var了一个变量num,但是并没有赋值,接着运行下去是调用函数fn(),执行函数时就会打印函数里的“我是fn函数”,然后是打印num值,由于此时的num仅仅是var声明了还没赋值所以会打印undefined,然后在给num赋值。
例2:
上面那个简单例子看懂了的话咱们可以再看一个难一点的,这个要是也会了那预解析相信你也基本掌握该怎么分析了,话不多说咱们上代码。
先看看不注释f1里面的console.log(b)和console.log(c )
f1();
console.log(c);
console.log(b);
console.log(a);
function f1() {
//函数内部定义的变量只能在函数内部使用
console.log(a); //undefined
console.log(b); //试试注释我们吧
console.log(c); //试试注释我们吧
var a=b=c= 9;
}
这一段代码会输出什么呢?
根据上面一题的方法分析咱们同样来看分成两个阶段来做:
这里可以简单提一下全局变量和局部变量:
在函数f1里var a=b=c= 9;就相当于:
var a;声明一个变量;
a=b=c=9;然后给9赋值给c,b,a
此时a有声名为函数f1里面的局部变量外界不可用,b,c未声明会转换成全局变量,外界可以读取到。
进行预解析:
即:
//正确的第一阶段预解析
function f1() {
//函数内部定义的变量只能在函数内部使用
var a ; //函数内部再次预解析,将var a;提前
console.log(a); //undefined
console.log(b); //未定义b,报错,后续就不会继续执行下去了
console.log(c); //
a=b=c= 9;
}
//第二阶段代码执行
f1();
console.log(c);
console.log(b);
console.log(a);
咱们先对函数里面的这里部分分析:
var a ;声明了a变量,咱们就可以打印出来a,由于赋值是在打印之后所以打印结果为undefined,然后此时console.log(b)和console.log(c ),这两个都还没var声明定义所以会直接打印会报错(报错结果为:Uncaught ReferenceError: b is not defined意思就是b还没定义,只要有一个报错后面就不会继续执行了),所以也就不需要继续看第二阶段的执行了,到这就报错了。
例2(改):
这个题其实咱们可以在改改,如我上面说的将f1里面的:
//console.log(b); 试试注释我们吧
//console.log(c); 试试注释我们吧
这个时候第二阶段就可以继续走下去了,注释后预解析以及执行代码:
function f1() {
//函数内部定义的变量只能在函数内部使用
var a ;
console.log(a); //undefind
//console.log(b);
//console.log(c);
a=b=c= 9;
}
f1();
console.log(c);//9
console.log(b);//9
console.log(a);//报错Uncaught ReferenceError: a is not defined
运行结果为什么会不一样呢?
在函数f1里var a=b=c= 9;就相当于:
var a;声明一个变量;
a=b=c=9;然后给9赋值给c,b,a。
a是函数里用var声明的,是一个局部变量,而b,c没有声明,变量未声明直接赋值,会被转换成全局变量,所以二阶段代码执行时f1里面的a声明了打印时还未赋值,为undefined,外面的c,b由于在里面没有用var声明为全局变量,外部也能读取,所以分别打印9,9,而a是函数里面声明的局部变量,外部不可用,所以a会报错,因为在外部没有定义,更别谈赋值了,相信看到这各位同学对预解析应该理解的也差不多了吧。