zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    ionic localstorage
    angular 中文鏈接
    把jqmobi 變成jQuery 的插件 從此使用jQuery
    jqmobi 的一些設置
    ionic ngcordova map 地圖
    ionic pull to refresh 下拉更新頁面
    json 對象的序列化
    鍵盤彈出,頁面佈局被推上去了.....
    Cordova V3.0.0中config.xml配置文件的iOS Configuration
    android ios 只能輸入數字 不能輸入小數點的 函數 cordova
  • 原文地址:https://www.cnblogs.com/hihao/p/7344684.html
Copyright © 2011-2022 走看看