標籤:進入 程式 可重複 範圍 重複 內建函式 流程 影響 counter
關於JS閉包
摘自吳留坡《原來JavaScript的閉包是這麼回事!》
一、相關概念
1.執行內容
在執行JS代碼時候的運行環境稱為執行內容。包括:全域代碼——首次執行代碼的預設環境;函數代碼——每當執行流程進入函數體時。
執行內容即當前代碼的執行環境或範圍。
2.執行過程
全域:啟動程式後,從全域執行內容開始,在全域執行內容中聲明的變數為全域變數
函數體:調用函數時,JS建立一個本地執行內容——本地執行內容擁有自己的變數集,即函數的局部變數——新的執行環境被拋到執行棧上。
(執行棧為用於跟蹤程式執行位置的機制)
函數遇到return或結束符號時:本地執行內容從執行棧跳出——函數將傳回值發送給調用上下文(調用上下文是調用此函數的執行內容,
可以是全域執行內容,也可以是另一個本地執行內容)——本地執行內容被銷毀(局部變數被銷毀)
3.詞法範圍
變數尋找過程:本地執行內容(局部變數)——調用上下文(局部變數/全域變數)——全域上下文(全域變數)
一個函數可以訪問在其調用上下文中定義的變數,此種現象稱為詞法範圍。
4.閉包原理
當聲明一個函數時,它包含一個函數定義和一個閉包。閉包是函數建立是聲明的變數。
eg:function createFn(){ let counter = 0; const myFn = function(){ counter = counter + 1; return counter; } return myFn; } 全域範圍中建立的函數也會建立一個閉包,但由於其是全域的,可以訪問全域範圍內所有變數,就無所謂閉包不閉包了。 *當一個函數返回另一個函數,並使用其調用上下文中變數時,才會真正涉及閉包。返回的函數可以訪問僅存在於其閉包中的變數。 當建立和傳遞一個函數或將其從另一個函數返回時,這個函數就帶有一個背包,背包中包含了所有在建立函數時聲明的變數。
二、對閉包的理解
閉包:重用局部變數,並保護該局部變數不受汙染的一種機制。(既有全域變數可重複使用的優點,又規避了全域變數易受汙染的缺點)
使用:
定義外層函數:定義受保護的局部變數(即閉包)——返回一個專門操作局部變數的內建函式對象
調用外層函數,獲得返回的內建函式對象
使用返回的內建函式對象,操作受保護的局部變數——唯一路徑
結論:同一次外層函數調用返回的多個內層函數對象共用一個受保護的變數
先後兩次外層函數調用返回的內層函數,分別使用各自受保護的變數副本,互不影響。
關於JS閉包