我所理解的javascript中函數的做用域和做用域鏈

本文爲原創,轉載請註明出處: cnzt       文章:cnzt-pjavascript

 http://www.cnblogs.com/zt-blog/p/6654308.htmlhtml

寫在前面java

  一週木有更新了,今天終於攻克了自行車難關,很是開心,特地來一更~ (那些捂嘴偷笑的人我看到大家了快把嘴閉上我會僞裝沒看見)。函數

  本文內容均基於我的理解,若有不認同,牆裂歡迎留言交流~~~spa

 

正文code

做用域htm

  簡單來講,javascript中有變量和函數的聲明/定義,有變量賦值和函數的執行 ,且遵循先聲明後執行原則,舉個例子:blog

1 var a = 1;  // 表達式
2 
3 function func(){ a = a + 1; }; // 函數聲明
4 
5 func(); // 函數執行

  上面的代碼等同於下面這個:ip

1 var a;  // 變量聲明
2 
3 function func(){ a = a + 1; }; // 函數聲明
4 
5 a = 1;   //執行變量賦值 
6 func(); // 函數執行 --> a=2

  

  理解了先聲明後執行原則以後,再來看做用域部分。簡單來講,javascript的做用域分兩類,一類是最外層做用域,如javascript標籤包裹起來的塊,或者常見的包含init()的塊,以下:作用域

1 //html文件中 script標籤包裹的塊
2 <script>
3  ... 4 </script>
5 
6 //外部 javascript文件中最外層的塊,通常包含init()
7 function init(){ ... } 8 ... 9 init()

  另外一類是當javascript碰到一個function時,這個function內部會造成一個它內部的做用域。以下:

/*相對於函數來講的做用域*/ ... //這裏是函數外部做用域
... function(){ //這裏是函數內部做用域
   // ... 
}

  第一次敲桌子--內部做用域能夠訪問外部做用域的值,反之行不通!好了,知道了這兩類做用域後,再來邊舉個栗子邊梳理做用域這個東西,栗子以下:

 1 var a = 1;  2 var b;  3 var c;  4 function f(){  5    b = 2;  6    var d = 3;  7    console.log(a);     //1 
 8    console.log(b);     //2
 9    console.log(d);     //3 
10 } 11 f(); 12 console.log(a);   //1
13 console.log(b);   //2
14 console.log(c);   //undefined
15 console.log(d);   //報錯: d is not defined

 

  上面的栗子已經註釋給出告終果,看到輸入的結果以爲正常麼?(我好像問了句廢話。。。)我仍是按照先聲明後執行的原則來看下,首先,從上到下,聲明瞭變量a,b,c,函數f,接着執行了a=1,執行函數f,這裏第二次敲桌子啦敲桌子!!-- 執行f的時候發生了什麼呢?不記得的翻上去看下,首次敲桌時說過了函數內部會造成新的內部的做用域。咱們來看下這個做用域,首先聲明d,而後執行b=2,d=3,console.log(a),第一次敲桌子的時候說了內部做用域能夠訪問外部做用域的值,so這裏a輸入爲1,接下來b和d都在函數內部賦過值了,因此console.log(b)和console.log(d)分別輸出2和3。至此,f已經執行完了(下劃線這部分),繼續,console.log(a)這裏a也已經賦過值會輸出1,console.log(b) -- 第三次敲桌子啦!!!--b聲明在外部做用域,賦值在f內部做用域,那麼這個賦值的結果在外部做用域還生效麼?答案顯而易見,生效的,輸出2(由於外部聲明瞭,這個變量就一直存在,其餘地方的賦值對其均有效)。再而後console.log(c) -- 第四次敲桌子!!!!c只是聲明瞭而已,並無賦值,所以輸出undefined。最後console.log(d) -- 第五次敲桌子!!!!!d爲啥會報錯呢?回頭看首次敲桌時是怎麼說的,「反之行不通」,即:函數外部不能訪問其內部定義的變量!再回來看d,d只是在f內部定義了,而外部並無權限訪問它,因此此次報錯d is not defined...

  /*注意區分undefined 和 d is not defined,一個未賦值,一個根本未聲明過。*/ 

 

做用域鏈

  看上面栗子中的5,7,8行,分別用到了a和b兩個變量,這兩個變量在f中聲明瞭麼?並無,那爲何還能輸出正確的值呢?做用域鏈就在這時候登場了。f中找不到相應的變量時,向上(外部)一層一層尋找直到最外層,找到則引用,找不到則報錯 -- 就是這麼簡單!

  

思考題

 1 var a = 10;
 2 var b = 5;
 3 function f(){
 4     console.log(a);
 5     var a = 20;
 6     console.log(a);
 7     var d = 30;
 8     var ff  = function(){a++; b++; d++; console.log(a); console.log(b); console.log(d);}
 9     return ff;
10 }    
11 
12 var c = f();
13 c();
14 f()();
15 c();

好好想一想這個思考題,注意return的部分,三思然後F12哦~~~

 

本文完。

相關文章
相關標籤/搜索