javascript给人的直观感受是,从上往下执行,但实际上却不是这样的,先看个例子

1. console.log(test); 
2. var test = "你好";
3. console.log(test); 
4. console.log(test2);
 

第1行结果为:undefined

第3行结果为:"你好"

第4行会报错:test2 is not defined

执行第1行时,test还没有定义,为什么没像第4行一样报错?

因为javascript执行时,在同一个作用域内是先编译再执行

编译的时候会编译 function 和 var 这两个关键词定义的变量,编译完成后从上往下执行并向变量赋值

所以执行第1行时, var test 已经执行过了,所以test不会报错,而test2就会报错

需要注意的是,对 var test 执行编译时,只是先定义了 test 这个变量,并不会把 "你好" 这个值赋给test,而是到第2行时才给test赋值的,这就是为什么第1行的执行结果是 undefined

对于上面的例子,可以这样理解

//先编译 var 定义的变量
1. var test;

//编译完成后,从上到下执行代码
2. console.log(test); 
3. test = "你好";
4. console.log(test); 
5. console.log(test2);


再看一下function的编译执行过程

例子

test();//执行结果是"你好"

function test() {
console.log("你好");
}


模拟编译执行过程

//找到 function 定义的部分进行编译
//以函数名作为变量名,同时用函数赋值
1. var test = function (){
console.log("你好");
};

//从头执行
2. test();


编译时,function和var是有些不一样的, function编译时会把function赋值给变量,而var编译时不会赋值

再看一个例子

var a = 1;
function test() {
a = 2;
return;

function a() {}
}
test();
console.log(a); //结果还是1


为什么结果是1不是2?我们模拟下编译执行过程就理解了

var a;
var test = function (){
//原因就在这
//这里 a 已经变成了局部变量
var a = function (){};

//这时给 a 赋值,实际是给局部变量a 赋值
a = 2;
return;
}
test();
console.log(a);