函数的解析过程
任何一个作用域 , 读取 js 都需要两个步骤 :
1 函数的预解析,简单来说就是找东西,找 var 和 function 遇到重名的直接被覆盖掉 , 预解析时不读赋值语句
2 逐行解读代码
看一下例题 , 这四个alert会弹出什么呢?
alert(a);
var a=1;
alert(a);
function a(){
alert(2);
}
alert(a);
var a=3;
alert(a);
function a(){
alert(4);
}
alert(a);
这道题的解析步骤
第一步,预解析的顺序,找var 和 function
alert(a);
var a=1; /*a = undefine*/
alert(a);
function a(){ /* 上个a被覆盖,此时 a = function{alert(2)} */
alert(2);
}
alert(a);
var a=3; /*上个a被覆盖,此时 a = 3*/
alert(a);
function a(){ /*上个a被覆盖 , 此时 a = function{alert(4)}*/
alert(4);
}
alert(a);
第二步 , 逐行解读代码
alert(a); /*预解析后, a = function{alert(4)}*/
var a=1;
alert(a); /*a被重新赋值 a = 1*/
function a(){ /*函数不调用,不会运行*/
alert(2);
}
alert(a); /* 此时 a = 1*/
var a=3;
alert(a); /*a被重新赋值 a = 3*/
function a(){ /*函数不调用,不会运行*/
alert(4);
}
alert(a); /*a的值仍然是3 a = 3*/
我们还需要注意,函数体是一个独立的作用域,会重新触发函数的预解析过程
if(){};for(){} 的大括号都不是作用域
局部变量可以直接访问全局变量,而且会更改全局变量,反之则不可以
我们来看一下这道题
var a=1;
function fn1(a){
alert(a);
a=2;
}
fn1(3);
alert(a);
第一步仍然是做预解析
var a=1; // 先找var 和 function
//找到了 a = undefine 和 fn1 = function{...}
function fn1(a){
alert(a); //函数体内部有了新的预解析过程
a=2;
}
fn1(3);
alert(a);
第二步,逐行解读代码
var a=1;
function fn1(a){
alert(a); /*接收到传参的时候相当于重新定义了一个 var a = 3
a=2; // 注意,此时在fn1内部的a被重新赋值为2
}
fn1(3); //传了一个参数3给fn1
alert(a); // 这里的a是全局变量,无法访问局部变量 所以结果为 1