執行環境(execution context,也有稱之爲執行上下文)是JS語言中最重要的一個概念。javascript
Javascript沒有代碼塊做用域的概念,局部做用域是針對函數來講的。前端
執行環境定義了變量或者函數有權訪問到的其餘數據,決定了他們的各自行爲。java
每一個執行環境都有一個與之關聯的變量對象(variable object),執行環境中定義的全部變量和函數都保存在這個對象中。沒法訪問,可是解析器在後臺執行中要用到。jquery
全局執行環境是最外圍的執行環境。根據ECMAScript實現的宿主不一樣,表示執行環境的對象也不同。Web瀏覽器中,全局執行環境是window對象,所以全局函數和全局變量都是做爲window的對象和方法。瀏覽器
某個執行環境中的全部代碼執行完畢後將被銷燬,全局執行環境在關閉網頁的時候纔會被銷燬。閉包
每一個函數都有本身的執行環境。當執行流進入函數的時候,函數的環境被推入到一個環境棧中。在函數執行之後,棧將其環境彈出,把控制權交給以前的執行環境。框架
當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈(scope chain)。函數
做用域鏈的做用是:是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域的前端始終是當前執行的代碼所在的環境變量的變量對象。若是這個環境是一個函數,則將其活動對象(activation object)做爲變量對象。做用域鏈中的下一個變量對象來自於包含環境。全局執行環境始終是做用域鏈中最後一個對象。ui
標識符解析始終是沿着做用域鏈一級一級地搜索標識符的過程,前端開始,逐級向上,直到找到標識符爲止,找不到就會報錯。this
函數的做用域鏈包含着兩個對象:它本身的變量對象(其中定義了arguments),和全局環境的變量對象。
當代碼在一個環境中執行時,會建立變量對象的一個做用域鏈(scope chain)。
做用域鏈的做用是:是保證對執行環境有權訪問的全部變量和函數的有序訪問。做用域的前端始終是當前執行的代碼所在的環境變量的變量對象。若是這個環境是一個函數,則將其活動對象(activation object)做爲變量對象。做用域鏈中的下一個變量對象來自於包含環境。全局執行環境始終是做用域鏈中最後一個對象。
標識符解析始終是沿着做用域鏈一級一級地搜索標識符的過程,前端開始,逐級向上,直到找到標識符爲止,找不到就會報錯。
函數的做用域鏈包含着兩個對象:它本身的變量對象(其中定義了arguments),和全局環境的變量對象。
雖然js中的執行環境總共就兩種:全局和函數(局部),可是仍是有其餘的辦法來延長做用域鏈。就是在做用域的前端添加一個臨時增長的變量對象。
具體使用:try...catch語句塊的catch塊;和with語句。
對於with語句來講,會將指定的對象添加到做用域鏈中。
function buildUrl(){
var qs = "?debug=ture";
with(location){
var url = href + qs;
}
return url;
}
js中沒有塊級做用域,只有全局做用域和函數做用域。注意在if語句||for語句中定義的變量會被添加到全局變量中。
可使用自執行語句來模擬塊級做用域。
使用var聲明的變量會被添加到最接近的環境中,函數內部就是函數做用域。若是初始化沒有使用var,就會被添加到全局做用域中。
沿着做用域鏈向上查找。
閉包與匿名函數不要搞混。
閉包:就是指有權訪問另外一個函數做用域中的變量的函數。建立閉包最多見的方式,就是在一個函數做用域內建立另外一個函數。而且返回另外一個函數。
須要閉包的緣由:當使用函數被調用時,會建立一個執行環境(上下文環境)以及相應的做用域鏈,使用arguments和其餘命名參數的值來初始化函數的活動對象(activation object)。函數執行過程就須要在做用域鏈中查找變量,查找過程不能向下,因此就須要閉包來讀取函數內部的變量。閉包會讓外層函數的變量一直存在於內存中。直到都不調用爲止。
外層函數的變量對象(活動對象)存在於內層函數的做用域鏈中。
閉包的問題:
一、過分使用閉包會形成內存佔用過多。
二、做用域鏈的這種配置引出一個問題,就是閉包只能取得包含函數中任何變量的最後一個值,閉包保存的是整個變量對象,而不是某個特殊的變量。
這裏打印的0~9是console.log打印的。最終保存的結果i都是10。
以上函數,在for循環中使用閉包,這樣最後讀取到的i是最後一個值。存在風險。改用以下的方式,將當前值保存下來,用一個自執行的閉包函數來保存變量,以後結果傳出。
函數的執行依賴於變量做用域,這個做用域在函數定義的時候決定的,不是在函數調用的時候決定的。
古老解釋對於閉包:函數對象經過做用域鏈來相互關聯,函數體內的變量均可以保存在函數做用域內。
閉包能夠捕捉到局部變量(和參數),並一直保存下來。
應用場景:一、閉包的典型框架應該就是jquery了。
二、閉包是javascript語言的一大特色,主要應用閉包場合主要是爲了:設計私有的方法和變量(模塊設計,自執行閉包)。
三、這在作框架的時候體現更明顯,有些方法和屬性只是運算邏輯過程當中的使用的,不想讓外部修改這些屬性,所以就能夠設計一個閉包來只提供方法獲取。
優勢:1. 邏輯連續,當閉包做爲另外一個函數調用的參數時,避免你脫離當前邏輯而單獨編寫額外邏輯。
2. 方便調用上下文的局部變量。
3. 增強封裝性,第2點的延伸,能夠達到對變量的保護做用。
缺點:閉包有一個很是嚴重的問題,那就是內存浪費問題,這個內存浪費不只僅由於它常駐內存,更重要的是,對閉包的使用不當會形成無效內存的產生。
關於閉包,就我本身的習慣而言,能不用就不用,若是非用不可,那就想辦法保持閉包對象的數量不多甚至惟一。
this對象在運行時是基於函數的執行環境綁定的:在全局函數中,this等於window,當函數被看成某個對象的方法調用的時候,this等於那個對象,非對象的函數調用,this都會指向window。也就至關於說,誰調用這個函數,this就指向誰。
匿名函數的執行環境具備全局性。這時候this對象指向window。
每當建立一個函數的時候,函數在被調用的時候自動獲取兩個特殊的變量,this和arguments。