JavaScript基础学习--08 JS作用域

 

一、浏览器
     1、“JS解析器”(至少分为两步骤)
          1.1     JS预解析(代码正式运行之前的准备工作)     “找一些东西并形成一个仓库”:var、function、参数
               1.1.1     var a = 1;                                        找到var a = undefined     (所有的变量在正式运行代码之前,都提前赋值:未定义;--》undefined)
               1.1.2     function fn(){ alert(......); }                  找到fn =  function fn(){ alert(......); }    (所有的函数在正式运行之前都是整个函数块)
               1.1.3     预解析规则
                    1.1.3.1     遇到重名的:只留一个------变量和函数重名,选择留下函数;同等级的留下后面那个(两个变量重名留后者;两个函数重名留后者)
                    1.1.3.2     表达式可以修改仓库中的值     
                         1.1.3.2.1     表达式:+-*/ Number()......     注意:函数只是一个声明,不是表达式
 
          1.2     逐行解读代码
 1 alert(a);   // function a(){alert(4);}
 2 var a = 1;  // 表达式能改变仓库中(预解析仓库)的值---> a = 1
 3 alert(a);   // 1
 4  
 5 function a() {  //函数声明不是表达式,不能改变a的值
 6     alert(2);
 7 }
 8 alert(a);   // 1
 9 var a = 3;  //  表达式能改变仓库中(预解析仓库)的值---> a = 3
10 alert(a);   // 3
11  
12 function a() {  //函数声明不是表达式,不能改变a的值
13     alert(4);
14 }
15 alert(a);   // 3
16  
17 a();     //a is not a function 报错,因为此时仓库中已经没有函数a了
18  
19  
20       
21 模拟浏览器解析:
22 预解析:
23 a = undefined
24 a = function a(){alert(2);}
25 a = undefined
26 a = function a(){alert(4);}
27 综上,最后 a = function a(){alert(4);}
28 所以 ......
     
二、作用域     只要是一个域,就会发生预解析。其中script标签是一个域
     1、每个script标签代表一个域块,从上到下的顺序,执行完一个script块中 js(预解析+逐行读代码) 才执行下一个script(如果有的话)
     2、script是全局变量、全局函数
     3、函数也是一个域,所以遇到函数执行时也会发生至少两步骤:预解析+逐行读代码     读代码:由里而外,作用域链
     4、{} 也是一个域,所以遇到 {} 执行时也会发生至少两步骤:预解析+逐行读代码
 1 var a = 1;  // a = 1
 2 function fn(){  //fn不变
 3     alert(a);   //  // undefined
 4     var a = 2;  //  // a = 2
 5 }
 6 fn();   // // 开始fn的预解析+逐行读代码
 7 alert(a);   //完成fn代码域的js解析,这是全局下的a ---> // 1
 8  
 9 模拟浏览器解析:
10 预解析:
11     a = undefined
12     fn = function fn(){alert(a); var a = 2;}
13 综上:读代码 //
14  
15 fn 中的预解析:
16     a = undefined
17 综上:读代码 // //
 
1 var a = 1; // a = 1
2 function fn() { //fn不变
3     alert(a); //  // 预解析的仓库中没有,此时作用域链发生作用,由里而外,局部没有,找全局中a = 1
4     a = 2; //  // a = 2
5 }
6 fn(); // // 开始fn的预解析+逐行读代码
7 alert(a); //完成fn代码域的js解析,这是全局下的a,并且被局部函数中的表达式改变了值 ---> // 2
模拟浏览器解析:
预解析:
a = undefined
fn = function fn() { alert(a); var a = 2; }
综上: 读代码 //
 
fn 中的预解析:
仓库为空
综上: 读代码 // //
 1 var a = 1; // a = 1
 2 function fn(a) { //fn不变
 3     alert(a); //  // 预解析仓库中有,就优先预解析仓库的值---> undefined
 4     a = 2; //  // a = 2 修改的是仓库中的a,没有修改全局的 a
 5 }
 6 fn(); // // 开始fn的预解析+逐行读代码
 7 alert(a); //全局中的a  1
 8  
 9  
10  
11 模拟浏览器解析:
12 预解析:
13 a = undefined
14 fn = function fn(a) { alert(a); var a = 2; }
15 综上: 读代码 //
16  
17 fn 中的预解析:
18 a = undefined //这是参数a,也是被预解析的对象
19 综上: 读代码 // //
 1 var a = 1; // a = 1
 2 function fn(a) { //fn不变
 3     alert(a); //  // 预解析仓库中有,并且传值a = 1(fn(a) == fn(var a = 实参a<如果有传参的话>))就优先预解析仓库的值---> 1
 4     a = 2; //  // a = 2 修改的是仓库中的a,没有修改全局的 a
 5 }
 6 fn(a); // // 开始fn的预解析+逐行读代码
 7 alert(a); //全局中的a  1
 8  
 9 模拟浏览器解析:
10 预解析:
11 a = undefined
12 fn = function fn(a) {alert(a);var a = 2;}
13 综上: 读代码 //
14  
15 fn 中的预解析:
16 a = undefined //这是参数a,也是被预解析的对象
17 综上: 读代码 // //

 

为了防止预解析浏览器兼容:尽量不要在if、for中定义函数、定义变量等等
1 alert(fn);  //预解析中if、for不是一个作用域,所以里面的变量相当于全局变量,所以弹出function fn(){alert(2);}
2             //但是,在FF浏览器中有兼容性,会报错,fn未定义!!!
3 if(true){
4     function fn(){
5         alert(2);
6     }
7 }
 
注意:for循环内部的函数与i
 1 for (var i = 0; i < 3; i++) {
 2     oBtn.onclick = function() {
 3         alert(i); //undefined     原因是函数内部是一个域,内部找到var i---> i预加载是undefined
 4         for (var i = 0; i < 3; i++) {
 5             ......
 6         }
 7     }
 8 }
 9  
10 for (var i = 0; i < 3; i++) {
11     oBtn.onclick = function() {
12         alert(i); //3     原因是函数内部是一个域,预加载时没有变量,于是第二部在逐行读代码的时候找不到i,到作用域链上(外部)找到i = 3,所以3
13         // for (var i = 0; i < 3; i++) {
14         //     ......
15         // }
16     }
17 }
18  
19 for (var i = 0; i < 3; i++) {
20     oBtn.onclick = function() {
21         alert(i); //3      原因是函数内部是一个域,预加载时没有变量,于是第二部在逐行读代码的时候找不到i,到作用域链上(外部)找到i = 3,所以3
22         for (i = 0; i < 3; i++) {
23             ......
24         }
25     }
26 }

 

posted @ 2017-08-11 10:48  HelenJ  阅读(175)  评论(0编辑  收藏  举报