JavaScript的预解析及案例

6

JavaScript的预解析及案例

author: histonevon@zohomail.com

environment: Google Chrome 84.0.4147.105 (正式版) 64位

edition: ES5

一、代码示例

有以下几段代码:

  1. 未声明就直接输出变量

 //num未声明
 console.log(num);

执行结果为:报错

preparsed0

  1. 变量预定义在变量使用前

 console.log(num);//使用
 var num = 10;//预定义

执行结果为:undefined

preparsed1

  1. 在函数声明前或后调用函数

 fn();//调用
 function fn() {
     console.log(11);
 }
 fn();//调用

执行结果为:正常

preparsed2

  1. 在匿名函数定义前通过变量名调用该函数

 fun();//调用
 var fun = function() {//匿名函数
     console.log(22);
 }

执行结果为:报错

preparsed3


二、JavaScript的预解析

  • JavaScript代码是由浏览器中的解析器来执行的

  • JavaScript解析器在运行JavaScript代码的时候分为两步:预解析代码执行

    • 预解析:js引擎会把js里所有的 var 变量声明和 function 函数声明提升到当前作用域的最前面

    • 代码执行:按照代码书写的顺序从上往下执行

  • 预解析分为变量预解析(变量提升)函数预解析(函数提升)

    • 变量提升:就是把所有变量声明提升到当前的作用域最前面,不提升赋值操作

      所以,上面第二例的语句实际上等价于:

       var num;//声明,不提升赋值
       console.log(num);
       num=10;//赋值

      可见,在num使用时还未定义,故结果为undefined

      同理,第四例相当于执行如下代码:

       var fun;//变量提升不给值
       fun();
       fun=function(){//赋值
            console.log(22);
       }

      fun声明后还未赋值,还不是函数,故报错"fun is not a function"

    • 函数提升:把所有的函数声明提升到当前作用域的最前面,不调用函数

      所以第三例为:

       function fn() {
           console.log(11);
       }
       fn();
       fn();

      即,等价于调用两次

      匿名函数不可提升(即第四例的情况)


三、预解析案例

  1. 结果是几?

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

test0

相当于执行了以下操作:

var num;//变量提升
function fun() {//函数提升
    //函数内部作用域的提升
    var num;//变量提升,尚未赋值
	console.log(num);//undefined
	num = 20;
}

num = 10;
fun();
  1. 结果是几?

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

test1

相当于执行了以下操作:

var num;
function fn() {
	var num;//声明后未赋值
	console.log(num);//undefined
	num = 20;//赋值
	console.log(num);//20
}
num = 10;
fn();
  1. 结果是几?

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

test2

var a;
function f1() {
	var b;
	var a;
	b = 9;
	console.log(a);//undefined
	console.log(b);//9
	a = '123';
}
a = 18;
f1();
  1. 结果是几?

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);
}

test3

  • var a = b = c = 9;相当于var a = 9;b = 9;c = 9;

    实际上,由于 = 为右结合,具体过程为:

    c = 9;
    b = c;
    var a = b;
  • 注意 若变量前没有var声明,直接赋值则为全局变量

  • 集体声明的方法为:

    var a = 9,b = 9,c = 9;

    或多行书写:

    var a = 10,
    	b = 11,
    	c = 12;
  • 故,函数内部三个值均为9,函数外部c,d为全局变量,也为9,a为局部变量,故报错"a is not defined"