JS预解析原理及例子

JS中的预解析是在面试的过程中经常会遇到的问题。在了解预解析之前,我们先来看看代码在浏览器中的执行机制。

JavaScript代码是由浏览器中的JavaScript解析器来执行的。JavaScript解析器运行JS代码又分为两步: 预解析 代码执行

(1) 预解析: js 引擎会把 js 里面所有的变量 var 还有函数 function 预先解析,提升到当前作用域的最前面
(2) 代码执行: 按照代码书写的顺序从上往下按进行执行

预解析分为 变量预解析 (变量提升)函数预解析 (函数提升)
(1) 变量提升:就是把所有的变量声明提升到当前作用域的最前面 不提升赋值操作
(2)函数提升:就是把所有的函数声明提升到当前作用域的最前面 并不调用函数


1. 变量提升的例1
        console.log(num);
        var num = 10;

函数输出: undefined
整个函数相当于执行了以下的操作
var 定义的变量在当前的作用域下进行了提升

        var num; 				//变量声明提升至当前作用域的最前面 但不提升赋值(num = undefined) 
        console.log(num);
        num = 10; 				//变量赋值

变量提升例2
定义了一个函数表达式

        fun();
        var fun = function () {
            console.log('你好');
        }

函数输出:在这里插入图片描述
整个函数相当于执行了以下的操作

        var fun; 				//声明了一个变量 未赋值
        fun(); 					//函数并不存在 调用时候必然报错
        fun = function () {
            console.log('你好');
        }

2. 函数提升例子
        fun();
        function fun() {
            console.log('你好');
        }

函数输出:你好
整个函数相当于执行了以下的操作

        function fun() { 		// 函数声明进行提升到当前作用域的顶部
            console.log('你好');
        }
        fun(); 					//再执行函数调用 正常输出

对比上面用函数表达式创建函数的方法,在调用的时候,必须写在函数表达式的下面。否则变量提升后,输出报错。


预解析案例一:
        var num = 10;
        fun();
        function fun() {
            console.log(num);
            var num = 20;
        }

函数输出:undefined
进行预解析后,相当于执行以下代码

        var num;            // 变量提升至当前作用域(window)
        function fun() {    // 函数提升至当前作用域
            var num;        // 变量提升至当前作用域(fun函数) 变量值undefined
            console.log(num);
            num = 20;       // 变量赋值
        }
        num = 10;           // 变量赋值
        fun();              // 函数调用

预解析案例二:

        var a = 18;
        fun();
        function fun() {
            var b = 9;
            console.log(a);
            console.log(b);
            var a = '123';
        }

函数输出:undefined 9
进行预解析后,相当于执行以下代码

        var a; 				// 变量提升 (作用域:window)
        function fun() { 	// 函数提升 (作用域:window)
            var b;  		// 变量b提升(作用域:fun函数)
            var a;			// 变量a提升(作用域:fun函数) a = undefined
            b = 9;			// 变量b赋值 b = 9
            console.log(a);
            console.log(b);
            a = '123';		// 变量a赋值
        }
        a = 18;				// 变量a赋值
        fun();

预解析案例三:

        fun();
        console.log(c);
        console.log(b);
        console.log(a);
        function fun() {
            var a = b = c = 9;
            console.log(a);
            console.log(b);
            console.log(c);
        }

函数输出:9 9 9 9 9 预解析.html:65 Uncaught ReferenceError: a is not defined
进行预解析后,相当于执行以下代码

        function fun() {		// 函数提升
            var a;				// 变量提升
            a = b = c = 9;		// 变量赋值 拆解a = 9;b = 9;c = 9;(具体分析在下面)
            console.log(a);
            console.log(b);
            console.log(c);
        }
        fun();					// 函数调用
        console.log(c);		
        console.log(b);
        console.log(a);

var a = b = c = 9; 相当于 var a = 9; b = 9; c = 9; 由于b和c是直接赋值,并没有var 声明,所以当做全局变量来看。
集体声明应该使用 var a = 9, b = 9, c = 9;用逗号进行分隔。


总结:在代码运行的过程中,先按照预解析进行代码重新排列分析,然后再按照作用域链查找对应变量和函数,再进行代码执行。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值