变量提升就像是JavaScript引擎使用小型代码起重机将所有var声明和函数函数声明提升到它们的作用域(所谓作用域是指可访问的变量和函数区域)在顶部。这句话的意思是:如果在函数体之外定义一个函数或者用var声明一个变量。那么变量和函数的作用域就会提升到整个代码的最高点。此时在任何地方访问这个变量或者调用这个函数都不会报错;而在函数体中定义函数或者使用var声明变量时,变量和函数的作用域会被提升到整个函数的最高点。此时在函数体的任何地方访问这个变量和调用定义的函数都不会报错。示例如下:console.log("gv1="+gv);//声明前访问变量show();vargv="javascript";console.log("gv2="+gv);function(){安慰。log("lv1="+lv);vatlv="js";console.log("lv2="+lv);}输出结果:gv1=undefined;lv1=undefined;lv2=js;gv2=javasript;在上面的代码中,第一行Dima和show函数中的第一行代码分别在变量声明前访问了gv和lv变量,第二行代码在函数定义前调用了show函数。从输出来看,上面的代码在声明前访问变量和在定义前调用函数都没有问题,因为变量提升了。上述代码运行前,预解析代码的逻辑如下:vargv;//变量声明提升到当前作用域的最高点varshow=functionshow(){varlv;console.log("lv1="+lv);//lv在声明的时候没有初始化,所以输出undefinedlv="js";console.log("lv2="+lv);//赋值给变量output:js}console.log("gv1="+gv1);//gv声明的时候没有初始化,所以输出undefinedgv="javascript";console.log("gv2="+gv);//变量赋值output:javascript从上面可以看出,正是因为var支持变量提升,所以可以在声明之前使用var声明的变量,而let和const不支持变量提升,所以它们声明的变量必须声明后才能使用。一般来说,javascript代码的执行包括两个过程:预解析过程和逐行解释过程。在逐行解释代码之前,javascript引擎需要进行预解析处理。在预解析过程中,当前作用域中的var变量声明和函数定义将被提升到作用域的顶部。
