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

編程語言 JavaScript HTML 板栗 達人科技 2017-04-05

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

寫在前面

一週木有更新了,今天終於攻克了自行車難關,非常開心,特意來一更~ (那些捂嘴偷笑的人我看到你們了快把嘴閉上我會假裝沒看見)。

本文內容均基於個人理解,如有不認同,牆裂歡迎留言交流~~~

正文

作用域

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

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

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

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哦~~~

本文完。

相關推薦

推薦中...