標籤:開發人員 總結 實現 等於 有一個 iot 控制 訪問 本地
【範圍】
javascript中的範圍可以理解為一個語句執行的環境大小,有全域的範圍,函數範圍和eval範圍。在JS中沒有塊級範圍。
講到範圍,不得不講執行環境,執行環境在JS中是最為重要的概念。執行環境定義了變數或函數有權訪問的其他資料,決定了他們各自的行為。每個執行環境都有一個與之關聯的變數對象,環境中定義的所有變數和函數都儲存在這個對象中。在web瀏覽器中全域環境被認為是window對象,某個執行環境中的所有代碼執行完畢後就被該環境銷毀,儲存在其中的所有變數和函數定義也隨即銷毀。
每個函數都有自己的執行環境。當執行流進入一個函數時,函數的環境就會被推入一個環境棧中。而在函數執行之後,棧將其環境彈出,把控制權返回給之前的執行環境。
當代碼在一個環境中執行時,會建立變數對象的一個範圍鏈。範圍鏈的用途是保證對執行環境有權訪問的所有變數和函數的有序訪問。範圍鏈的前端始終是當前執行的代碼所在環境的變數對象。範圍鏈中的下一個變數對象來自包含(外部)環境,在下一個變數對象則來自於在下一個包含環境,這樣一直延續到全域執行環境,全域執行環境的變數對象始終都是範圍鏈中的最後一個對象。
需注意的是:在局部範圍中定義的變數可以在全域環境和局部環境中互動使用。內部環境可以通過範圍鏈訪問所有的外部環境,但外部環境不可以訪問內部環境中的任何變數和函數。每個環境都可以向上搜尋範圍鏈,以查詢變數和函數名,但任何環境都不可以通過向下搜尋範圍鏈而進入另一個執行環境。
範圍鏈本質上是一個指向變數對象的指標列表,他只引用但不包含變數對象。
【閉包】
閉包是指有權訪問另一個函數範圍中的變數的函數,這裡要把它與匿名函數區分開(匿名函數:建立一個函數並將它賦值給一個變數,這種情況下建立的函數叫匿名函數,匿名函數的name屬性是Null 字元串),建立閉包的常見方式就是在一個函數內部建立另一個函數。閉包儲存的是整個變數的對象。
閉包的作用:在函數執行過程中,為讀取和寫入變數的值,就需要在範圍鏈中尋找變數,這時靈活方便的閉包就派上用場,我們知道當一個函數被調用時就會建立一個執行環境及相應的範圍鏈,那麼閉包就會沿著範圍鏈擷取到開發人員想要的變數及元素。
註:在維基百科中是這樣定義閉包的:閉包(也稱詞法閉包或函數閉包)是指一個函數或函數的引用,與一個引用環境綁定在一起。這個引用環境是一個儲存該函數每個非局部變數(也叫自由變數)的表。——閉包不同於一般的函數,它允許一個函數在立即詞法範圍外調用時,仍可訪問非本地變數。
閉包靈活方便,也可以實現封裝,這樣就只能通過對象的特定方法才能訪問到其屬性。但是,不合理的使用閉包會造成空間的浪費,記憶體的泄露和效能消耗。
【原型和原型鏈】
講到原型鏈,不得不講講用於建立對象的原型模式:我們建立每一個函數都有一個prototype(原型)屬性,這個屬性是一個指標,指向一個對象,而這個對象的用途是包含可以由特定的所有執行個體共用的屬性和方法。從字面意思理解,那麼prototype就是通過調用建構函式而建立的那個對象執行個體的原型對象。使用原型對象的好處是可以讓所有對象執行個體共用它所包含的屬性和方法。我們可以通過對象執行個體訪問儲存在原型中的值,但卻不能通過對象執行個體重寫原型中的值。如果我們在執行個體中添加了一個與原型執行個體中同名的屬性,那麼我們在執行個體中建立該屬性,該屬性將會屏蔽原型中的屬性。
無論什麼時候,只要建立一個新函數,就會根據一組特定的規則為函數建立一個prototype(原型)屬性,這個屬性指向函數的原型對象。
原型鏈:用於實現JS中的實現繼承。(許多語言都支援兩種方式的繼承:介面繼承和實現繼承。介面繼承只繼承方法簽名,而實現繼承則繼承實際的方法。由於函數沒有簽名,在ECMAScriot中只能實現實現繼承。
原型鏈作為實現繼承的主要方法,其基本思想是利用原型讓一個參考型別繼承另一個引用繼承的屬性和方法。瞭解一下建構函式、原型和執行個體的關係:每個建構函式都是一個原型對象,原型對象都包含一個指向建構函式的指標,而執行個體都包含一個指向原型對象的內部指標。假如我們讓原型對象等於另一個類型的執行個體,那麼此時的原型對象將包含一個指向另一個原型的指標,相應的另一個原型中包含著一個指向另一個建構函式的指標。如此層層遞進,就構成了執行個體與原型的鏈條。這就是原型鏈的概念。
當函數調用時,需尋找和擷取的變數和元素都會通過原型鏈機制一層層的往上搜尋在原型對象或繼承來的對象中獲得。
當函數被建立,就有了範圍,當被調用時,就有了範圍鏈,當被繼承時就有了原型鏈,當需要擷取範圍鏈或原型鏈上的變數或值時,就有了閉包。
Javascript-基礎概念總結