探讨一个问题,JavaScript 中,变量可以在使用后声明,也就是变量可以先使用再声明。

例如如下代码:

        //1.先使用变量后申明
        console.log(num);
        var num = 66;
        //2.先调用函数后定义
        fn();
        function fn() {
            console.log('先调用函数后申明');
        }
        //3.匿名函数先调用后定义会报错
        fun();
        var fun = function () {
            console.log('匿名函数先调用后申明会报错');
        }

image-20201231145245727

观察运行结果,按照c语言常识的话,前面两个都应该会报错呢,但是并没有,让人难受的是,情况1 输出undefined ,情况2还执行了,最后一个反而还报错了。

JavaScript的预处理

js引擎会把js的执行分为两步,1.预解析 2.代码执行

预解析其实就一句话,js引擎会把变量申明var 和 函数定义function,提升到当前作用域的最前面执行,但是不执行赋值操作

这样我们就很容易理解上面的问题了。

  1. 情况1 先使用变量后申明

            console.log(num);
            var num = 66;
    

    解释器预处理的时候,先把声明var num; 放到当前作用域的最前面执行,但是没有赋值,所以就会输出undefined啦

    		var num;//提升到前面执行
            console.log(num);//没有赋值不知道是啥变量,所以输出undefined.
            var num = 66;
    
  2. 情况2 先调用函数后定义

            fn();
            function fn() {
                console.log('先调用函数后申明');
            }
    

    编译器其实遇到定义函数就会提前到当前作用域最前面定义(不管你的函数在多么后面定义),不会调用函数。

  3. 情况3 匿名函数先调用后申明会报错

            fun();
            var fun = function () {
                console.log('匿名函数先调用后申明会报错');
            }
    

    预处理的时候,会把var fun ;提升到最前面,但是不执行赋值操作,当你执行fun();编译器不知道他是函数会报错的。

    相当于如下代码。

            var fun;
    		fun();
            var fun = function () {
                console.log('匿名函数先调用后申明会报错');
            }
    

练习一下

        var num = 10;
        fun();
        function fun() {
            console.log(num);
            var num = 20;
        }

分析,js引擎会把变量申明var 和 函数定义function,提升到当前作用域的最前面执行,但是不执行赋值操作

那么 function fun(){....}会被提前定义好,里面的var num;也会提前被申明。值得注意的是这里有两个num 但是作用域不同,执行fun里面的num 是{}里定义num

代码其实可以看成这样子

	var num;
            function fun() {
               var num;
               console.log(num);
               var num = 20;
           }
			var num = 10;
           fun();
          

所以输出 undefined。

结语

假期的第五天
微信小程序

努力成长的程序员