1. 程式人生 > >JavaScript基礎(11.JS難點:作用域詳解)

JavaScript基礎(11.JS難點:作用域詳解)

先來個其他語言的例子:


不用仔細考慮它是什麼意思,注意一點即可:

在內層大括號裡面定義了一個string型的name變數,卻在大括號外面用它,因此會報錯。

我們繼續:

在Python中:


情況一可以執行,而情況二會出錯。

到底是為什麼呢?

這裡用簡單的一句話來解釋就可以:

在其他語言中是作用域以塊({})為單位的,在Python裡面作用域是以函式作為單位的。、

因此,函式內部定義的變數可以在函式內部任意使用,但是在函式外部就不能用了。

如這裡的func()可以成功執行,但是print(name)就會出錯。

接下來我們來看JS:

1.它預設是以函式為作用域的!所以它和Python是一樣的。


成功!

對了,在console裡面要換行的話,按shift+回車,否則就直接執行了,當時寫這裡的時候還不知道。

2.函式的作用域在沒有執行之前(即在沒有被呼叫之前)就已經建立!

3.函式的作用域存在作用域鏈,並且也是在被呼叫之前建立!


一個函式套一個函式產生作用域鏈。

現在這個函式執行後輸出tony,解釋見下

當console.log(xo)執行時候,首先找當前函式下的xo變數,找到tony,如果註釋掉tony,它就會找外一層函式裡面的xo變數,找到eric,如果再註釋掉它,就會找外部變數xo,找到alex。如果alex不存在,就會報錯!

我們繼續深入:


這裡的func函式的返回值為inner函式,因此ret()就相當於是呼叫inner函式

然而並不會輸出alex,輸出的是eric

先執行ret = func()

作用域鏈裡面的xo就是eric,然後返回了inner。

開始執行ret() ,先找最內側沒有xo,然後找外層xo就是eric

繼續深入:


這時候會輸出的是tony;

因為前一步的ret = func() 執行後,func作用域鏈裡面的xo變數由eric變成tony,

ret()執行的時候,現在最內層找,找不到,然後外層找,外層的xo變成了tony,所以輸出tony

4.JavaScript特有的:內部區域性變數會提前宣告:

當直譯器解釋函式的時候,生成作用域鏈,在生成的同時,還會有另外一個操作:

宣告所有的變數,但是並沒有定義。

這句話的意思就是,函式裡邊如果第一行要使用某個變數,但是在第n行定義了它。這在C++裡面會報錯的,但是在JS裡面會會輸出一個undefined。