溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

Javascript中的閉包知識點講解

發(fā)布時間:2021-08-31 18:53:06 來源:億速云 閱讀:119 作者:chen 欄目:web開發(fā)

本篇內(nèi)容介紹了“Javascript中的閉包知識點講解”的有關(guān)知識,在實際案例的操作過程中,不少人都會遇到這樣的困境,接下來就讓小編帶領(lǐng)大家學習一下如何處理這些情況吧!希望大家仔細閱讀,能夠?qū)W有所成!

1. 詭異的閉包

javascript 中有一個特殊的特性 - 閉包,對于 .NET 程序員來說,比較熟悉的是面向?qū)ο蟮某绦蛟O(shè)計 OOP,  而來自函數(shù)式語言的閉包則顯得比較詭異,許多程序員對它敬而遠之。

對于閉包我們還是要從函數(shù)式語言的特點說起。

不知道你有沒有發(fā)現(xiàn),在 javascript 中沒有 public ,private 之類的關(guān)鍵字,也沒有 class  ,雖然也存在對象一說,但是對象的地位遠遠沒有在 C# 中是一等公民,在 js  中,沒有對象你也可以一樣寫程序。它只是一種數(shù)據(jù)的表示形式而已,可有也可無。

2. 閉包何來?

如何在 javascript 實現(xiàn)數(shù)據(jù)的保護呢?閉包就是實現(xiàn)它的利器,這需要我們放下普通的對象,理解一下 javascript 的工作原理。

在 javascript  中,可以在函數(shù)中定義新的函數(shù),這種嵌套函數(shù)還可以作為函數(shù)的返回值,被外部的變量所引用。在普通的程序設(shè)計語言中,比如 C  中,雖然也存在函數(shù)指針的概念,但是,所謂的函數(shù)指針僅僅是一段代碼的地址而已,而 javascript 中返回的函數(shù)引用,則不限于此。

在 C 語言中,在函數(shù)運行的時候,局部變量是保存在堆棧中的,函數(shù)執(zhí)行完畢,系統(tǒng)所做的是彈出堆棧。

實際上,在 javascript  中,函數(shù)每次執(zhí)行的時候,注意是運行時,系統(tǒng)會同時創(chuàng)建一個此次函數(shù)運行的環(huán)境對象,而此次運行期間的局部變量則關(guān)聯(lián)在這個環(huán)境對象上,在普通不返回函數(shù) 的普通函數(shù)中,函數(shù)執(zhí)行完畢,則環(huán)境對象也一起釋放。而如果函數(shù)返回了定義在外部函數(shù)中的嵌套函數(shù),那么,這個環(huán)境對象將不會釋放,也就是說,這個時候, 返回了一個看得見的函數(shù)對象,還附帶了一個看不見的暗物質(zhì) - 外部函數(shù)的環(huán)境對象。

看得見的函數(shù)對象加上隱含的環(huán)境對象就是閉包。

這個環(huán)境對象只能通過這個函數(shù)隱式訪問,我們并沒有它的引用,也無法直接訪問它。結(jié)果就是實現(xiàn)了信息的隱藏。

3. 實現(xiàn)私有的數(shù)據(jù)

考慮下面的代碼

function outer() {     var name = "Alice";     var inner = function () {         return name;     }     return inner; }  var fn = outer(); alert(fn());

在這個例子中,看起來簡單的 fn 函數(shù)背后,其實暗藏了在執(zhí)行 outer 函數(shù)時期創(chuàng)建的環(huán)境對象,所以通過 fn 可以得到 Alice 這個名字,而且沒有其他的渠道允許得到這個名字。

4. 為什么數(shù)據(jù)搞亂了?

再看另外一個經(jīng)典的例子。

<body>     <div>         <a href="#">Click Me!</a>         <a href="#">Click Me!</a>         <a href="#">Click Me!</a>     </div>     <script type ="text/javascript">         function main(links) {             for (var i = 0; i < links.length; i++) {                 links[i].onclick = function () {                     alert(i + 1);                 }             }         };         main(document.getElementsByTagName("a"));     </script>  </body>

彈出的是多少呢?感覺有三次循環(huán),應(yīng)該彈出 1, 2, 3。運行一下,你會看到實際上是 4, 4, 4!

是不是非常詭異?

從閉包的角度來說,則非常簡單,main 函數(shù)執(zhí)行了幾次呢?只有一次,在執(zhí)行的時候創(chuàng)建了一個閉包對象,其中引用了定義在 main 中的局部變量 i,在循環(huán)體中,實際上創(chuàng)建了三個內(nèi)部函數(shù),它們引用的都是同一個環(huán)境對象。這些函數(shù)注冊到鏈接的 onclick 事件上,其實也就是已經(jīng)傳出了函數(shù) main,所以,main 的環(huán)境對象也就悄悄地成為了暗物質(zhì),而循環(huán)完成之后 i 已經(jīng)最終被賦予了 3 這個值,三個函數(shù)訪問的是同一個環(huán)境對象中的 i, 所以,在點擊鏈接的時候看到 4 這個結(jié)果也就正常了。

5. 解鈴還需系鈴人

如果希望得到的是  1, 2, 3 這個結(jié)果又該怎么辦呢?

我們可以定義一個內(nèi)部函數(shù),讓它執(zhí)行三次,這個將會創(chuàng)建三個對應(yīng)的環(huán)境對象,我們可以使得這三個環(huán)境對象包含不同的值。

function main(links) {     var inner = function (elem, i) {         elem.onclick = function () {             alert(i + 1);         };     };     for (var i = 0; i < links.length; i++) {         var elem = links[i];         inner(elem, i);     } };

由于 inner 函數(shù)執(zhí)行了三次,所以將會創(chuàng)建三個不同的環(huán)境對象,每個環(huán)境對象中的  i 都是不同的值。這樣注冊到 onclick 中的函數(shù)就可以訪問到不同的值了。

閉包的概念

這里,我們可以看一下閉包的概念了。來自 Wiki 的說明是這樣的

在計算機科學中,閉包(Closure)是詞法閉包(Lexical Closure)的簡稱,是引用了自由變量的函數(shù)。這個被引用的自由變量將和這個函數(shù)一同存在,即使已經(jīng)離開了創(chuàng)造它的環(huán)境也不例外。所以,有另一種說法認為閉包是由函數(shù)和與其相關(guān)的引用環(huán)境組合而成的實體。

“Javascript中的閉包知識點講解”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實用文章!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI