作用域-变量和函数提升

变量和函数的提升可以分成两步:
- 1 js先预解析:把变量和函数声明提升到作用域顶端,我理解的意思是在浏览器中找一些东西
- 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:

扫描二维码关注公众号,回复: 2341496 查看本文章
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

应该能读懂加理解了吧

猜你喜欢

转载自blog.csdn.net/zm_miner/article/details/79298298