知識總結:謝靜賢、湯昊
在javascript中作用域是非常重要的,本文將會說明作用域以及我們在工作,以及面試中的一些面試題,如果有不足的地方希望大家可以評論指出來,自己一定會及時的改正錯誤,避免大家走入一些誤區。
一:作用域
二.預解析??
三.作用域鏈
四.函數和變量提升
五.預解析中的一些變態機制?
一、作用域
一般情況下,一段代碼中所用到的名字并不總是有效可用的,而限定這個名字(變量)的可用性的代碼范圍就是這個名字的作用域,可用有效的減少變量名沖突
1、js的作用域(es6)之前:全局作用域,局部作用域
2、全局作用域:整個script標簽?或者是單獨的JS文件
3、局部作用域(函數作用域),在函數內部就是局部作用域,這個變量名只能在函數內部使用
4、變量作用域
根據作用域的不同,變量分為全局變量,局部變量
?注意
如果在函數內部沒有聲明直接賦值的變量也叫全局變量?
?函數的形參也是局部變量
?全局變量:只有瀏覽器關閉的時候才會銷毀,比較占內存
?局部變量:當程序執行完畢就會銷毀,比較節約內存
5、現階段JS沒有塊級作用域
在es6中有塊級作用域
塊級作用域?{}?if{}?for{}
6、作用域鏈
內部函數訪問外部函數?采用的就是鏈式這種結果就是作用域鏈?(就近原則)
二.預解析
1、什么是預解析:
預解析:在當前作用域下,js代碼執行之前,瀏覽器會把帶有var和function關鍵字的提前進行聲明(var只聲明)或定義(function聲明并定義),并在內存中安排好。然后再從上到下執行js語句。
2、預解析的作用:
變量提升(Hoisting):在JS中,瀏覽器會把定義在后面的(變量或函數)提升到前面當前作用域的top處。也就是說在當前作用域中我們在js代碼未執行到聲明之前就可以使用了;
var和function預解析的不同
Var
var在預解釋的時候,只進行提前的聲明,只要是通過var定義的,不管變量或者函數,都是賦值undefined;
Function
function在預解釋的時候提前的聲明和定義都完成了,但是它儲存數據的空間里存儲的是字符串,沒有任何意義。
三.作用域鏈
JavaScript代碼中至少有一個作用域, 即全局作用域。
凡是代碼中有函數,那么這個函數就構成另一個作用域。
如果函數中還有函數,那么在這個作用域中就又可以誕生一個作用域。
將這樣的所有的作用域列出來,可以形成的結構就稱之為作用域鏈。
四. 函數和變量提升
1.? 函數提升(函數預解析):函數的聲明會被提升到當前作用域的最上面,但是不會調用函數。
2.變量提升(變量預解析):變量的聲明會被提升到當前作用域的最上面,變量的賦值不會提升。
變量提升和函數提升基本上是面試必問題目
下面我們針對這個例子解析一下
我們知道變量和函數定義都會提升到作用域最前邊
唯一需要確認的是變量和函數的先后順序
我們預想 函數是用會不會提升到最前邊呢?
按照我們預想的解析結果應該是
// undefined // undefined // 報錯
理由 函數在上var在下,第一個console時a未賦值,其結果是undefined,if為false 只剩最后一個console也是undefined 最后a is not a function.
不過結果是
我機智的認為 預想錯了?
這樣?對比一下結果人工解析結果 :1、a() 2、1 3、1 4、a() 報錯
瀏覽器執行結果:
看到這里一切完美,不過我還是重新搜索了一些高質量文章,發現我錯了,雖然執行結果是對的,不過瀏覽器和人工解析還是不一樣的,和我們最開始預想的一樣,函數優先。
既然標題說到了變量 和 函數,我們就一塊來說說
首先上邊已經說到我們預想和認為的是錯的。
正確解析順序是這樣的
但是,這個但是很重要瀏覽器執行結果是:
why?這就要講講我所了解到的原理。
同名變量和函數,函數會提升到最前邊,變量其次,那為什么結果不是我們人工執行的undefined呢?原因是 變量會被忽略,是的是忽略。。。
完美!
還有呢?是的還有同名變量是怎樣的順序,同名函數是怎樣的順序。
同名變量
同名變量,聲明會被提升,后邊會忽略。
同名函數
我想你已經猜到了,同名函數會被覆蓋。
五.預解析中的一些變態機制
不管條件是否成立,都要把帶var的進行提前的聲明
JavaScript進行預解析的時候,會忽略所有if條件,因為在ES6之前并沒有塊級作用域的概念。本例中會先將num預解析,而預解析會將該變量添加到window中,作為window的一個屬性。那么 'num' in window 就返回true,取反之后為false,這時代碼執行不會進入if塊里面,num也就沒有被賦值,最后console.log(num)輸出為undefined。
return下的代碼依然會進行預解析
函數體中return下面的代碼,雖然不再執行了,但是需要進行預解析,return中的代碼,都是我們的返回值,所以不進行預解析。
您的點贊是我繼續下去的動力,謝謝!