JavaScript之閉包的基本知識

閉包(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 閉包

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章