预解析:在当前作用域下,js运行之前,会把带有var和function关键字声明的变量先声明,并在内存中安排好。然后从上至下解析js语句。而且function的声明优先于var声明。
作用域链: 由子级到父级寻找变量
浏览器在解析js代码时是从上到下解析的
解析顺序如:
(1)预解析
找var和function
(2)逐行代码解析
表达式
函数调用
fn1()函数内部再发生
{
(1)预解析
(2)逐行代码解析
}
案例1:
var a = 1; //全局变量
function fn1(a) { //把a作为参数传进来,但是并没有在他的局部作用域定义
console.log(a); //函数内预解析为a=undefined
a = 2; //后又将a改为2
}
//调用方法
fn1();
console.log(a); //在全局中找到的a=1
【js预解析器】通俗的讲就是在浏览器解析js代码前,他的预解析器会首先找到一些变量或把代码中的一些变量放入自己的仓库,在进行解析。
案例2:
注意:遇到重名,变量和函数重名,就留下函数,与上下关系没有关系,注:只先找var ,function声明的
console.log(a); //存在预解析的仓库里面: a(){console.log(5);}
var a=1;
console.log(a); //1
function a(){console.log(2);}
console.log(a); //1
var a=3;
console.log(a); //3
function a(){console.log(4);}
console.log(a); //3
function a(){console.log(5);}
具体过程:
1.找到第一个var存值为undefined(注意不会为其赋值为1,而是undefined)
2.function a(){console.log(2);}代替前面var
3.var =3不会替代function
4.function a(){console.log(5);}替代function a(){console.log(4);}替代function a(){console.log(2);}
5.预解析结果:把a=function a(){console.log(4);}存在预解析的仓库里面
案例3:利用局部改全局
var str=""; //全局变量
function fn1(){
var ss='局部变量~~~';
str=ss;
}
fn1();
//console.log(a);//Uncaught ReferenceError: ss is not defined
console.log(str);//局部变量~~~,利用局部改全局
案例4:函数内部调用外部函数:
function fn2(){
var a='这是fn2方法!';
fn3(a); //调用函数
}
fn2();
function fn3(b){
console.log(b);//注:与fn2里面的a不一样,输出为这是"fn2方法!"
}
注:以下不是作用域
if(){}
for(){}
while{}
总结:
1、变量的声明提前了----提前到当前所在的作用域的最上面
2、函数的声明也会被提前---提前到当前所在的作用域的最上面