做用域
1. 全局做用域
2. 函數做用域
這裏扯出來下js的函數聲明和變量聲明提高,直接來兩段代碼閉包
if (!a in window) { var a = 1; } console.log(a) //undefined
嗯,爲何呢?由於var聲明的變量會變量聲明提高,因此至關於執行if判斷的時候a變量已經聲明過了,而此時a是一個全局變量既是window對象的一個屬性,因此這裏壓根沒有進if判斷,因此這裏打印出來的是undefined
再來一段坑坑的代碼函數
(function (){ var a = b = 10; })() console.log(b) // b是10 console.log(a) // a是局部變量因此在這裏打印a的時候會報錯
在函數中var a = b = 10,b暴露爲全局變量,由於賦值是從右往左進行的,也就是說這一行先執行b=1,這時候b就是全局變量了,沒有被var過。而後是var a = b;a被聲明瞭,是局部變量。你賦值給a,b=1,是不存在的,var a=b=1,就能夠等同於,b=1;var a=b;this
那麼下面這裏的問題也很容易知道答案嘍spa
var a; var b; (function () { console.log(a) // undefined console.log(b) //10 var a = b = 10; console.log(a); // 10 console.log(b); // 10 })(); console.log(a) // undefined console.log(b) // 10
做用域鏈是怎麼回事呢code
1. 執行環境和做用域 (函數第一次調用的時候會建立做用域鏈和執行環境,並把做用域鏈賦值給一個內部屬性[scope]),而後使用this、arguments和其餘命名參數來初始化函數的活動對象。但在做用域鏈中,外部函數的活動對象始終處於第二位,外部函數的外部函數始終處於第三位...直至做用域鏈的終點全局執行環境。
2. 活動對象
3. 變量對象(每一個執行環境都會有一個變量對象)對象
先來個函數吧!!!blog
var a = 10, b = 20; function sum (a, b) { return a + b; } var result = sum(a, b)
// 在sum函數被調用的時候,會建立它的做用域和執行環境,而後,使用arguments和其餘命名參數初始化其活動參數。在做用域鏈中,它的外部函數處於第二位,外部函數的外部函數處於第三位......,直到做用域鏈的終點全局執行環境內存
通常,在函數執行完畢後,局部活動對象就會銷燬,內存中僅僅保存全局做用域(全局執行環境的變量對象)。作用域
閉包中的做用域鏈又是怎麼回事呢???io
在另外一個函數內部定義的函數會將包含函數的活動對象添加到它的做用域鏈中。外部函數執行完後,雖然做用域鏈會銷燬,可是因爲內部函數仍然在引用這個活動對象,外部函數的活動對象不會銷燬,一直保存到內存中,直到內部函數被銷燬後,外部函數的活動對象纔會被銷燬。
閉包會攜帶包含他的函數的做用域鏈,因此比其餘函數佔用更多的內存。過分使用閉包會致使內存使用過多。