javascript引擎的工作模式是“先解析后执行”,先解析申明的变量/函数,然后再一行一行执行代码。这造成的结果,就是所有变量/函数的声明语句,都会被提升到代码的头部,这就叫做变量/函数提升(hoisting)
javascript执行分两个阶段:解析阶段(解析变量申明、解析函数申明、解析形参)、执行阶段
变量提升:
示例1:
var a;
console.log(a);//undefined
a=2;
解析阶段:解析找到var关键字定义的变量,创建一个变量a的内存,给未赋值的变量一个默认值undefined;
执行阶段:遵从从上往下执行的规则,console.log(a)在未赋值前就执行了,所以打印出来的值是undefined,然后才执行的a=2 这个赋值阶段;
示例2:
a=10;
console.log(a); //10
var a;
解析阶段:javascript在解析的时候都是先找到var关键字创建的变量和funtion关键字创建的函数进行预解析的,所以这里先找到的还是var a;这个变量进行解析,创建一个变量a的内存,给未赋值的变量一个默认值undefined;
执行阶段:遵从从上往下执行的规则,先执行a=10;变量赋值这个操作,然后在执行console.log(a);,所以结果就是10;
直观代码示例2:
var a;
a=10;
console.log(a); //10
函数提升:(具名函数两种申明方式:函数申明、函数表达式)
(函数申明)示例1:
a(); //1
function a(){
console.log(1);
}
解析阶段:解析找到function关键字定义的函数,创建一个函数a的函数内存;
执行阶段:函数申明的函数提升到了最顶端,所以在执行调用的时候就能找到它;
(函数表达式)示例2:
a(); //Uncaught TypeError: a is not a function
var a=function(){
console.log(2);
}
解析阶段:函数表达式创建的函数,其实就是创建一个未赋值的普通变量,这个时候同样是创建一个变量a的内存,然后给变量一个默认值undefined;
执行阶段:从上往下执行,执行到a()调用函数的时候,是找不到这个函数的,所以就报错了,最后才执行的是变量赋值这一段;
直观代码(函数表达式)示例2:
var a;
a(); //Uncaught TypeError: a is not a function
a=function(){
console.log(2);
}
函数申明优先于变量申明:
示例1:
a(); //1
var a= function(){
console.log(2);
}
function a(){
console.log(1);
}