閉包理解
1. 如何產生閉包?
* 當一個嵌套的內部 ( 子 ) 函數引用了嵌套的外部 ( 父 ) 函數的變量 ( 函數 ) 時,產生閉包
2. 閉包到底是什麼?
* 使用 Chrome 調試查看
* 理解一:閉包是嵌套的內部函數 ( 絕大部分人 )
* 理解二:包含被引用變量 ( 函數 ) 的對象 ( 極少數人 )
* 注意:閉包存在於嵌套的內部函數中
3. 產生閉包的條件?
* 函數嵌套
* 內部函數引用了外部函數的數據 ( 變量 / 函數 )
* 執行函數定義 ( 比如執行外部函數時 )
(執行函數定義就會產生閉包,不用調用內部函數,調用外部函數時會預處理產 生執行上下文,那時就可以執行內部函數的定義了)
這種函數定義,在22行就已經產生閉包。
如果把函數定義賦給變量這種形式,在22行處就不能產生閉包,因為預處理時會把fn2當做變量提升,賦值undefined,也沒有執行函數定義。也就無法產生閉包。
這種方式聲明的函數對象,要在 26 行整個函數定義執行完才會產生閉包。
常見的閉包
1. 將函數作為另一個函數的返回值
2. 將函數作為實參傳遞給另一個函數調用
看內部函數創建幾次,就看外部函數執行幾次。
反覆執行內部函數的過程中,閉包為什麼沒有消失?
如果沒有閉包,在執行完 var f =fn1() 後 a 就消失了,後面的 f() 沒法從 fn1 裡面調 a 。
閉包裡面有 msg ,沒有 time
閉包的作用
1. 使用函數內部的變量在函數執行完後,仍然存活在內存中 ( 延長了局部變量的生 命周期 )
2. 讓函數外部可以操作 ( 讀寫 ) 到函數內部的數據 ( 變量 / 函數 )
問題:
1. 函數執行完後,函數內部聲明的局部變量是否還存在?
一般不存在,存在於閉包中的變量才可能存在。
( 「可能」是指:閉包所在的函數對象不成為垃圾對象 )
按理說,函數執行完後其內部的屬性都會被釋放,但如果該函數的某個內部函數 對象通過在外部函數內 return 的方式賦給某個全局變量,
那麼這個函數對象就存 活下來了,而和它有關聯的閉包里的局部變量也會存活。
2. 在函數外部能直接訪問函數內部的局部變量嗎?
不能。但我們可以通過閉包來讓外部操作它。
( 「通過閉包來讓外部操作」是指:函數嵌套一個內部函數,在這個內部函數對 象里寫類似 a++ 這種可以修改函數內部變量的操作,
然後把這個內部函數對象賦給 外部的全局變量,就可以在外部操作函數內部的局部變量)
閉包的生命周期
1. 產生:在嵌套內部函數定義執行完時就產生了(不是在調用)
2. 死亡:在嵌套的內部函數成為垃圾對象時
閉包死亡(包含閉包的函數對象成為垃圾對象)
f = null
閉包應用 _ 自定義 JS 模塊
* 具有特定功能的 js 文件
* 將所有的數據和功能都封裝在一個函數內部(私有的)
* 只向外暴露一個包含 n 個方法的對象或方法
* 模塊的使用者,只需要通過模塊暴露的對象調用方法來實現對應的功能
第一種
第二種