摘要:每次循環(huán)都會創(chuàng)建一個以立即執(zhí)行函數(shù)為作用域的變量,原來在程序中函數(shù)訪問的是外部變量,現(xiàn)在訪問的是這一閉包中的變量。
這是篇文章主要是講一下對閉包這一概念的理解。討論閉包之前,我們先從一個經(jīng)典的例子說起
// 程序1 var arr = [] for(var i = 0; i < 3; i++){ arr[i] = function () { console.log(i) } } arr[0]() // 3 arr[1]() // 3 arr[2]() // 3
大家都知道,這段代碼最終輸出都為3。因為函數(shù)調(diào)用的時候循環(huán)已經(jīng)結(jié)束了所以 i 等于3,更為重要的是,es6之前沒有塊作用域,變量 i 的作用域不在for循環(huán)中,而在for循環(huán)之外。如果我們想要看到輸出結(jié)果依次為0,1,2,就得用到閉包了。否則,除非我們能在每次循環(huán)的過程中調(diào)用函數(shù),因為只有在循環(huán)進行的過程中 i 才會處于0,1,2的狀態(tài)。比如像這樣:
// 程序2 for(var i = 0; i < 3; i++){ (function () { console.log(i) })() } // 0 // 1 // 2
必須要在循環(huán)進行時調(diào)用哦,像下面這樣都不行!
// 程序3 for(var i = 0; i < 3; i++){ setTimeout(function () { console.log(i) }, 0) } // 3 // 3 // 3
當(dāng)然程序2這樣寫已經(jīng)失去意義了,這個程序的目的就是要給數(shù)組加幾個函數(shù)供以后調(diào)用,而不是馬上就要調(diào)用它。閉包主要就是用來解決這樣的問題,它讓函數(shù)可以訪問到函數(shù)所被創(chuàng)建時的上下文環(huán)境,不論這個函數(shù)在什么時候被調(diào)用。所以閉包產(chǎn)生的條件有兩個,一是函數(shù)能通過變量作用域規(guī)則訪問到它被創(chuàng)建時的上下文環(huán)境,例如程序1,函數(shù)只是簡單的訪問了外部的變量 i,嚴格上講不算閉包。二是函數(shù)在其它地方執(zhí)行時,函數(shù)依然能夠記住并訪問到它所被定義時的上下文環(huán)境,我們使用閉包來對程序1進行修改:
// 程序4 var arr = [] for(var i = 0; i < 3; i++){ (function () { var j = i arr[i] = function () { console.log(j) } })() } arr[0]() // 0 arr[1]() // 1 arr[2]() // 2
不同的是這次增加了立即執(zhí)行函數(shù)并在里面定義變量 j ,我們可以把立即執(zhí)行函數(shù)稱為 fn 。每次循環(huán)都會創(chuàng)建一個以立即執(zhí)行函數(shù)為作用域的變量 j ,原來在程序1中函數(shù)訪問的是外部變量 i ,現(xiàn)在訪問的是fn這一閉包中的變量 j 。fn執(zhí)行結(jié)束時 j 本應(yīng)被回收,但是由于該作用域內(nèi)還定義了一個內(nèi)部訪問了變量 j 的函數(shù),該函數(shù)在未來可能被執(zhí)行,所以 j 被“記住”了,也就是作用域鏈被保存了。我們可以把fn稱為一個閉包,閉包內(nèi)可以定義函數(shù)并且這些函數(shù)可以訪問閉包中定義的變量,例如:
function fn(){ var a = 1; return function(){ console.log(a) } } var module = fn() module() // 1
fn返回的函數(shù)通過閉包能夠訪問到 a。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/105628.html
摘要:回憶我一年前,雖然使用過很多,但卻完全不理解閉包是什么。就算你,也會在循環(huán)完成時,輸出次當(dāng)然,不要以為主要的原因是延遲函數(shù)會在循環(huán)結(jié)束時才執(zhí)行,不然我為什么會在閉包這一節(jié)用使用這個例子,哈哈。 前言 在了解閉包的概念時,我希望你能夠有JavaScript詞法作用域的知識,因為它會讓你更容易讀懂這篇文章。 感觸 對于那些使用過JavaScript但卻完全不理解閉包概念的人來說,理解閉包可...
摘要:由于匿名函數(shù)的作用域是全局性的,因此閉包的通常指向全局對象調(diào)用返回值為而不是我們預(yù)期的,在閉包中函數(shù)作為某個對象的方法調(diào)用時,要特別注意,該方法內(nèi)部匿名函數(shù)的指向的是全局變量。 有人的地方就有江湖,有函數(shù)的地方就有this。而this在不同的環(huán)境下,又表現(xiàn)為不同的形式,難免讓人有種此this非彼this的疑惑 在java等面向?qū)ο蟮恼Z言中,this指的就是當(dāng)前對象,而在jav...
摘要:詞法作用域的查找規(guī)則是閉包的一部分。因此的確同閉包息息相關(guān),即使本身并不會真的使用閉包。而上面的創(chuàng)建一個閉包,本質(zhì)上這是將一個塊轉(zhuǎn)換成一個可以被關(guān)閉的作用域。結(jié)合塊級作用域與閉包模塊這個模式在中被稱為模塊。 你不知道的JS(上卷)筆記 你不知道的 JavaScript JavaScript 既是一門充滿吸引力、簡單易用的語言,又是一門具有許多復(fù)雜微妙技術(shù)的語言,即使是經(jīng)驗豐富的 Jav...
閱讀 1863·2021-11-25 09:43
閱讀 1504·2021-09-02 15:21
閱讀 3471·2019-08-30 15:52
閱讀 1511·2019-08-30 12:48
閱讀 1308·2019-08-30 10:57
閱讀 2939·2019-08-26 17:41
閱讀 688·2019-08-26 11:59
閱讀 1379·2019-08-26 10:41