JS面向對象之做用域

做用域

詞法做用域

做用域

表示的就是範圍,即做用範圍java

  • 就是一個名字在什麼地方能使用,在什麼地方不能使用編程

    塊級做用域

    級別的做用範圍
// 在 c , java 等編程語言中,下面的語法報錯
    {
        var num = 123;  // 應該用int , 這裏是僞代碼
        {
            console.log(num);   // 123
        }
        console.log(num);   // 報錯
    }

在 js 中採起詞法做用域

詞法(代碼)做用域,就是代碼在編寫過程當中體現出來的做用範圍,代碼一旦寫好,不用執行,他的做用範圍就已經肯定好了,這個就是所謂的詞法做用域
在 js 中的詞法做用域規則
1. 函數容許方位函數外的數據
2. 整個代碼結構中只有函數能夠限定做用域
3. 做用規則首先是提高規則分析
4. 就近原則若是當前做用規則有了名字,就不考慮外面的名字瀏覽器

在 js 中做用域分析方法

1. 先進行預解析,分析預解析過程
    * 程序在執行過程, 會先將代碼讀取到內存中檢查. 會將全部的聲明在此時進行標記. 所謂的標記就是
讓 js 解釋器知道有這個名字, 後面在使用名字的時候, 不會出現未定義的錯誤. 這個標記過程就是提高.
    * 聲明
    1. 名字的聲明, 標識符的聲明( 變量名聲明 )
        * 名字的聲明就是讓咱們的解釋器知道有這個名字
        * 名字沒有任何數據與之對應
    2. 函數的聲明
        * 函數聲明包含兩部分
        * 函數聲明與函數表達式有區別, 函數聲明是單獨寫在一個結構中, 不存在任何語句, 邏輯判斷等結構中
        * 首先函數聲明告訴解釋器有這個名字存在. 該階段與名字聲明同樣
        * 告訴解釋器, 這個名字對應的函數體是什麼**(函數名和函數體綁定連接)**
2. 再進行代碼執行過程

常見的簡單做用域問題

例子 1:編程語言

var num = 123;
    function foo(){
        console.log(num);
    }
    foo();  // 輸出 123

分析函數

  1. 預解析code

    變量num變量名提高
       函數foo函數名提高
  2. 代碼執行內存

    num賦值123,函數內區域爲獨立區域,可使用外部數據,可是如今變量名相同,覆蓋外面的值
       函數foo執行
       函數區域中變量num變量名提高
       輸出num 爲undefined
       num賦值456
       輸出num 爲456

例子 2:作用域

if(false){
        var num = 123;
    }
    console.log(num);   // 輸出undefined

分析io

  1. 預解析console

    變量名num提高
  2. 執行代碼

    if判斷爲false,不進入
       輸出num,num定義未賦值,爲undefined

例子 3:

var num = 123;
    function foo(){
        var num = 456;
        function fn(){
            console.log(num);   //  輸出456
        };
        fn();
    }
    foo();

分析

  1. 預解析

    變量名num和函數名foo聲明提高,函數名foo和函數體連接
  2. 執行代碼

    num = 123, 賦值
       執行函數, 函數內部聲明提高,變量名num和函數名fn
       變量num=456, 執行函數fn
       輸出num, fn函數內部沒有num,向上級尋找
       num=456, 輸出num

例子 4:

var num = 123;
    function foo1(){
        var num = 456;
        function foo2(){
            num = 789;
            function foo3(){
                console.log(num);   // 輸出789
            }
            foo3();
        }
        foo2();
    }
    foo1();     // 輸出456
    console.log(num);   // 輸出123

分析

  1. 預解析

    變量名num和函數名foo1聲明提高,函數名foo1和函數體綁定
  2. 執行代碼

    num = 123, 賦值
       執行函數foo1, 變量名num和函數名foo2聲明提高, 函數名foo2和函數體綁定
       num = 456, 賦值
       執行函數foo2, num在foo2函數中沒有, 訪問上級foo1獲得num,  num = 789, 賦值函數名foo3聲明提高而且綁定函數體
       執行函數foo3, 輸出num, foo3中沒有num,訪問上級,獲得num = 789
       輸出num爲789
       跳出函數, 輸出num爲123

例子 5:

if ( ! 'a' in window ) {
        var a = 123;
    }
    console.log( a );   // undefined

分析

  1. 預解析

    變量a聲明提高
  2. 執行代碼

    判斷window中是否存在a,a存在
       判斷爲false,不執行if中的代碼
       輸出a,爲undefined

複雜的做用域問題

例子 1

if ( true ) {
        function f1 () {
            console.log( 'true' );
        }
    } else {
        function f1 () {
            console.log( 'false' );
        }
    }
    f1();

分析
新版瀏覽器

  1. 預解析

    無,函數f1被瀏覽器認爲是函數表達式,不進行變量名提高
  2. 執行代碼

    if判斷進入true
       執行函數表達式f1
       輸出結果爲true

舊版瀏覽器

  1. 預解析

    函數f1變量聲明提高,f1函數名和最後一個函數體鏈接在一塊兒
  2. 執行代碼

    if判斷進入true
       執行f1
       輸出false

例子 2

if ( false ) {
        function f1 () {
            console.log( 'true' );
        }
    } else {
        function f1 () {
            console.log( 'false' );
        }
    }
    f1();

分析
新版瀏覽器

  1. 預解析

    無,f1爲函數表達式,沒有進行聲明提高
  2. 執行代碼

    if判斷
       執行f1
       輸出false

舊版瀏覽器

  1. 預解析

    函數名f1,聲明提高,函數名和最後一個函數體連接在一塊兒
  2. 執行代碼

    if判斷
       執行f1
       輸出false

例子 3

var num = 123;
    function f1() {
        console.log( num );
    }
    function f2() {
        var num = 456;
        f1();
    }
    f2();

分析

  1. 預解析

    聲明提高,變量num,函數名f1,f2,函數名和函數體連接
  2. 執行代碼

    num = 123
       執行函數f2
       變量num賦值456
       執行函數f1
       輸出num,函數裏面沒有,向上尋找,上級爲(0級做用域鏈),num=123,輸出num爲123

例子 4

var num = 123;
    function f1() {
        console.log( num );
    }
    function f2() {
        num = 456;
        f1(num);
    }
    f2();

分析

  1. 預解析

    變量名num,函數名f1,f2聲明提高,函數名和函數體連接一塊兒
  2. 代碼執行

    num=123
     執行函數f2
     num=456,f2中沒有num,向上級尋找獲得num爲123,將num = 123賦值,num = 456
     執行f1, f1中沒有num, 向上級尋找獲得num爲456
     輸出num,num=456,輸出num456
相關文章
相關標籤/搜索