JavaScript解析器在运行JavaScript代码的时候会进行预解析,也就是提前对代码中的var变量声明和function函数声明进行解析,把它们解析到内存,然后再去执行其他的代码。
首先我们来看看当我们未定义一个变量而直接访问它时会出现什么情况。
console.log(a);
直接报错,由于未定义,不能访问到变量a。
如果先访问变量,再声明变量呢
console.log(a); var a;
输出结果为undefined,可见在JS中,会先预解析var声明的变量,给它分配一个内存,再执行其他代码,所以此时虽然我们先访问变量,再声明它,但由于预解析机制,a变量的内存已经存在了,我们可以根据下列的代码更加深刻的体会:
console.log("1、a="+a); var a = 10; console.log("2、a="+a); //输出为 1、a=undefined 2、a=10
此代码的执行顺序为:(1)解析var变量a,给它分配内存;(2)执行console.log(“1、a=”+a);,由于此时还未执行赋值语句,所以结果为undefined;(3)给变量a赋值为10;(4)执行console.log(“2、a=”+a);由于此时已赋值,所以结果为10。
代码如下:
console.log(fn()); function fn(){ var i = 1,j = 2; var sum = i+j; return sum; } //输出结果: 3
从这个例子我们可以看出JS解析器对于函数的预解析是先解析fn函数的定义,再执行其他代码,所以此时虽然我们先访问了函数fn,但由于fn已经被解析了,所以依旧得到了我们想要的值。
那如果我们声明了两个相同名字的变量与函数,有一个声明将会被覆盖,那么是哪一个会被覆盖呢,我们可以通过以下代码研究以下:
console.log(a); var a = 2; function a(){ return 2; } console.log(a);
它的执行顺序其实是:
function a(){ return 2; } var a; console.log(a); a = 2; console.log(a);
输出结果为:
[Function: a]
2
函数提升优先级比变量提升要高,且不会被变量声明覆盖,但是会被变量赋值覆盖。
JS代码执行前,会将函数声明与变量声明提升到当前作用域最顶端,进行预解析,然后再从上到下执行其他代码。