先看一段报错的代码:
<script> var web="hello world!"; console.log(web); //class 是关键字 var class="class"; </script>
Uncaught SyntaxError: Unexpected token class
并没有输出"hello world!",因为程序在自上到下执行之前,解析器会事先把代码分析一遍(预解析)。在分析的过程中,就已经执行的变量的提升。
1、变量提升
ES6之前我们一般使用var来声明变量,使用var声明的变量会发生提升, 变量提升就是把我们所写的变量声明代码提升到它所在作用域的顶端去执行,在代码所在的位置来赋值。
在控制台直接输出一个变量,会出现异常,
<script>
console.log(web); </script>
Uncaught ReferenceError: web is not defined
如果在输出语句的下面声明此变量,就不会抛出异常了。
<script> console.log(web); //输出undefined var web="hello world"; </script>
因为解析器在执行之前分析代码的时候,就在变量的声明提升到了作用域的顶端。类似如下代码:
<script> var web; console.log(web); //输出undefined web = "hello world"; </script>
demo:
<script> function test() { if (false) { var web=123; } console.log(web); } test(); //输出undefined </script>
变量提升的效果:
<script> function test() { var web; if (false) { web=123; } console.log(web); } test(); //输出undefined </script>
2、函数提升
函数声明的两种方式:声明式和字面量式。
//声明式 function test() {} //字面量式 var test1 = function () {}
字面量式的函数提升效果跟变量提升的效果是一样的,因为字面量式的函数只是一个具体的值。
<script> console.log(test); function test(){ console.log("test"); } /* 输出: ƒ test(){ console.log("test"); } */ </script>
执行顺序为:
<script> function test(){ console.log("test"); } console.log(test); //输出undefined /* 输出: ƒ test(){ console.log("test"); } */ </script>
但是声明式的函数提升和字面量式的函数提升略有不同,声明式的函数提升是整个代码块提升到它所在的作用域的最开始执行的地方,拥有最高的优先级。