JavaScript函数的预解析

先聊聊什么是预解析

预解析指的就是函数的编译和执行的过程,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会报错,因为在外部没有定义,更别谈赋值了,相信看到这各位同学对预解析应该理解的也差不多了吧。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值