变量和函数的提升可以分成两步:
- 1 js先预解析:把变量和函数声明提升到作用域顶端,我理解的意思是在浏览器中找一些东西
- var ; 函数function a(){}; 参数;
所有变量,在正式运行代码之前都提前赋了一个值:未定义;
只要有以上中的任意一个,就预解析; - 在预解析时遇到重名的只留下后一个;
- 变量和函数重名的,就留下函数.
- var ; 函数function a(){}; 参数;
- 2.逐行解读代码
- 表达式:= + - * / % ++ -- 参数......
- 表达式可以修改预解析的值
直接上代码应该更好理解一点,先来个简单的代码,理解下
示例1:
alert(a);
var a=1;
结果:undefined
- 首先预解析 :
通过var function 参数 ,在代码中有var 那么就把var a 提升到作用域顶端。 - 接着读代码:
第一行:alert(a);往预解析中找a,恩,找到了a 因为所有变量,在正式运行代码之前都提前赋了一个值:未定义;
a=undefined;
示例2:
alert(a);
var a=1;
function a(){alert(2);}
结果: function a(){alert(2);}
还是两步:
- 预解析: var ; 函数function a(){}; 参数;
var a=undefined;
function a(){alert(2);}
变量和函数重名了,干掉变量留下了函数 - 读代码
第一行:现在预解析中只有函数了,所以a的值就为function a(){alert(2);}
示例3:
alert(a); // function a(){alert(4);}
var a=1;
alert(a);//1
function a(){alert(2);}
alert(a);//1
function a(){alert(2);}
var a=3;
alert(a);//3
function a(){alert(4);}
alert(a);//3
a();//报错
- 预解析 var ; 函数function a(){}; 参数;
var a=undefined;
function a(){alert(2);} //干掉前面变量 保留它
function a(){alert(2);} //干掉前面函数 保留它
var a //变量打不过函数 依旧保留前面函数
function a(){alert(4);} //干掉前面函数 保留它 //最终保留的是此函数
读代码时预解析中值得变化
function a(){alert(4);}-->a=1--->a=3 - 读代码
alert(a) // 往预解析中找 只有function a(){alert(4);}
var a=1; 表达式可以修改预解析的值 ,干掉函数--> a=1;
alert(a)//1预解析中找到a ,a=1;
function a(){alert(2);} 函数只是一个声明不会改变预解析的值
alert(a);//1预解析中找到a 还是 a=1;
var a=3; //改变预解析中a的值
alert(a);//3
function a(){alert(4);}//函数只是一个声明不会改变预解析的值
alert(a);//3
a()--->3()肯定报错 a为3不是函数 肯定不能调用;
示例 4
var a=1;
function fn1(){
alert(a); //1
a=2;
}
fn1();
alert(a); //2
- 预解析 var ; 函数function a(){}; 参数;
var a=undefined;
读代码时预解析中值得变化
a=undefined-->a=1-->a=2 - 读代码
var a=1; 表达式可以修改预解析的值 ,干掉函数--> a=1;
fn(); 函数调用 又要预解析和读代码- 预解析:
什么都没有 找不到 var ; 函数function a(){}; 参数;中的任意一个 - 读代码:
alert(a) 找不到a往上找 找到a=1;那么a=1;
a=2; 表达式可以修改预解析的值 ,干掉a=1--> a=2;
alert(a)此时预解析中a的值已经被修改为2了
- 预解析:
示例5
var a=1;
function fn1(a){
alert(a);
a=2; //1
}
fn1(a);
alert(a); //1
和上面代码相比只是添加了行参和实参
预解析 var ; 函数function a(){}; 参数;
var a=undefined;
读代码时预解析中值得变化
a=undefined-->a=1-
读代码
var a=1; 表达式可以修改预解析的值 a=undefined--> a=1;
fn1(a); 函数调用 又要预解析和读代码- 预解析:
此时传递了一个实参a, a的值接受了全局变量a的值所以a=1.在function fn1(a){}中的形参实际上是function fn1(var a=1){} 所以在此次预解析时 a=undefined;
读代码时预解析中值得变化
a=undefined-->a=1-->a=2- 读代码:
从参数开始读 本质是局部变量 a=1
alert(a) 找到a=1;那么a=1;
a=2; 表达式可以修改此次预解析的值 ,干掉a=1--> a=2;
alert(a);在全局中a的值还是1 ,不会被改为2
- 预解析:
示例6:
var a=1;
function fn1(a){
alert(a);//undefined
a=2;
}
fn1();
alert(a); //1
此时没有传实参
预解析 var ; 函数function a(){}; 参数;
var a=undefined;
读代码时预解析中值得变化
a=undefined-->a=1-
读代码
var a=1; 表达式可以修改预解析的值 a=undefined--> a=1;
fn1(); 函数调用 又要预解析和读代码- 预解析:
在function fn1(a){}中的形参实际上是function fn1(var a){} ,因为没有传实参,所以在此次预解析时 a=undefined;
读代码时预解析中值得变化
a=undefined-->a=2- 读代码:
从参数开始读 本质是局部变量a=undefined;
alert(a) 找到a;那么a=a=undefined;;
a=2; 表达式可以修改此次预解析的值 , a=2.
alert(a);在全局中a的值还是1 ,不会被改为2
- 预解析:
应该能读懂加理解了吧