閉包(closure)
1.如何產生閉包?
當一個嵌套的內部(子)函數引用了嵌套的外部(父)函數的變量(函數),內部函數被定義時(即外部函數被執行時),就產生了閉包。
外部函數執行幾次就產生了幾個閉包
2.閉包到底是什麼?
* 使用chrome查看
* 理解一:閉包是嵌套的內部函數(絕大多數人)
* 理解二:包含被引用變量(函數)的對象(極少數人)
* 注意:閉包存在於嵌套的內部函數中
3.產生閉包的條件?
- 函數嵌套
- 內部函數引用了外部函數的數據(變量/函數)
如下代碼可以產生閉包
function fn1 () {
var a = 2
function fn2 () { //執行函數定義時纔會產生閉包(不用調用內部函數)
console.log(a)
}
}
fun1()
注意:以下代碼執行到第3行時,內部函數才被定義,此時才產生閉包
function fn1 () {
var a = 2
var fn2 = function() { //執行函數定義時纔會產生閉包(不用調用內部函數)
console.log(a)
}
}
fun1()
4.常見的閉包——閉包的兩種用法
1、將函數作爲另一個函數的返回值
function fn1(){
var a = 2
function fn2(){
a++
console.log(a)
}
return fn2
}
var f = fn1()
f() //3
f() //4
外部函數執行幾次就產生了幾個閉包,這裏 fn1 只執行了 1 次,所以產生 1 個閉包。
2、將函數作爲實參傳遞給另外一個函數調用
function showDelay(msg,time){
setTimeout(function(){
alert(msg)
},time)
}
showDelay('atguigu',2000)
閉包的作用
使函數內部的變量在函數執行完後,仍然存活在內存中(延長了局部變量的生命週期)
讓函數外部可以操作(讀寫)到函數內部的數據(變量/數據)
問題???
函數執行完後,函數內部聲明的局部變量是否還存在?
答:一般是不存在了,存在於閉包中的變量纔可能存在
在函數外部能直接訪問函數內部變量嗎?
答:不能,但我們可以通過閉包讓外部操作它
閉包的生命週期
產生:在嵌套內部函數定義執行完時就產生了(不是在調用)
死亡:在嵌套的內部函數成爲垃圾對象時
閉包的應用——自定義JS模塊
-
具有特定功能的js文件
-
將所有的數據和功能都封裝在一個函數內部(私有的)
-
只向外暴露一個包含n個方法的對象和函數
-
模塊的使用者,只需要通過模塊暴露的對象調用方法來實現對應的功能
創建一個myModule.js文件
function myModule(){
var msg = 'My World'
function doSomething(){
console.log('doSomething()' + msg.toUpperCase())
}
function doOtherthing(){
console.log('doOtherthing()' + msg.toLowerCase())
}
return {
doSomething:doSomething,
doOtherthing:doOtherthing
}
}
在index.html文件中引用myModule.js文件
<!DOCTYPE html>
<html lang='en'>
<head>
<meta charset='UTF-8'>
<title>閉包的應用——自定義的JS模塊</title>
</head>
<body>
<script type='text/javascript' src='myModule.js'></script>
<script type='text/javascript'>
var module = myModule()
module.doSomething()
module.doOtherthing()
</script>
</body>
</html>
通過函數自調用,將函數/數據暴露在window對象上,這樣可以在inde.html直接寫函數/名字使用不用對象.函數/變量的形式
(function(window){
var msg = 'My World'
function doSomething(){
console.log('doSomething()' + msg.toUpperCase())
}
function doOtherthing(){
console.log('doOtherthing()' + msg.toLowerCase())
}
window.myModule2 = {
doSomething:doSomething,
doOtherthing:doOtherthing
}
})(wondow)
閉包的缺點
缺點:
函數執行完後,函數內的局部變量沒有被釋放,佔用內存時間會邊長
容易造成內存泄漏
解決:
能不用閉包就不用
及時釋放
內存溢出:
一種程序運行出現的錯誤
當程序運行需要的內存超過了剩餘的內存時,就會拋出內存溢出的錯誤
內存泄漏
佔用的內存沒有及時釋放
內存泄漏積累多了就容易導致內存溢出
常見的內存泄漏:
1 意外的全局變量(比如在函數內部不使用var聲明的變量)
2 沒有及時清理的計時器或回調函數
3 閉包