摘要:最準(zhǔn)確地來解釋對(duì)的應(yīng)用方法是詞法作用域的查找規(guī)則即在的函數(shù)作用域中無法找到則向上一級(jí)所嵌套的的作用域中查找,而這些規(guī)則只是閉包的一部分。而閉包的神奇之處可以阻止作用域被銷毀,被回收。
什么是閉包?
當(dāng)函數(shù)可以記住并訪問所在的詞法作用域時(shí),就產(chǎn)生了閉包,即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行的。
下面用一些代碼來解釋這個(gè)定義:
function foo() { var a = 2; function bar() { console.log(a); // 2 } bar(); } foo();
這是閉包嗎?
技術(shù)上來講,也許是。但根據(jù)前面的定義,確切地說并不是。最準(zhǔn)確地來解釋 bar() 對(duì) a 的應(yīng)用方法是詞法作用域的查找規(guī)則(即在 bar() 的函數(shù)作用域中無法找到 a,則向上一級(jí)所嵌套的 foo() 的作用域中查找),而這些規(guī)則只是閉包的一部分。
下面再看一段代碼,清晰地展示了閉包:
function foo() { var a = 2; function bar() { console.log(a); } return bar; } var baz = foo(); baz(); // 2 這就是閉包的效果
函數(shù) bar() 的詞法作用域能夠訪問 foo() 的內(nèi)部作用域,然后將 bar() 函數(shù)本身作為一個(gè)值類型進(jìn)行傳遞。在這段代碼中,我們將 bar 所引用的函數(shù)對(duì)象本身作為返回值。在 foo() 執(zhí)行后,其返回值賦值給變量 baz 并調(diào)用 baz(),實(shí)際上只是通過不同的標(biāo)識(shí)符引用調(diào)用了內(nèi)部函數(shù) bar()。
在 foo() 執(zhí)行后,通常會(huì)期待 foo() 的整個(gè)內(nèi)部作用域都被銷毀。而閉包的神奇之處可以阻止作用域被銷毀,被回收。那么是誰再使用這個(gè)內(nèi)部作用域?是 bar() 本身在使用。bar() 擁有覆蓋 foo() 內(nèi)部作用域的閉包,使得該作用域能夠一直存活,以供 bar() 在之后任何時(shí)間進(jìn)行引用。這個(gè)引用就叫做閉包。
再據(jù)兩個(gè)例子:
function foo() { var a = 2; function baz() { console.log(a); //2 } bar(baz); } function bar(fn) { fn(); // 這就是閉包 }
function wait(message) { setTimeout(function timer(){ console.log(message); },1000); } wait("Hello World");循環(huán)和閉包
先看下面的例子:
for(var i=1; i<=5; i++){ setTimeout(function timer() { console.log(i); },i*1000); }
這段代碼在運(yùn)行時(shí)會(huì)以每秒一次的頻率輸出五次6.為什么會(huì)這樣呢?
首先解釋6是怎么來的。這個(gè)循環(huán)的終止條件是 i<=5。條件首次成立時(shí) i 的值是6.因此,輸出顯示的是循環(huán)結(jié)束時(shí) i 的最終值。
延遲函數(shù)的回調(diào)會(huì)在循環(huán)結(jié)束時(shí)才執(zhí)行,當(dāng)定時(shí)器運(yùn)行時(shí)即使每個(gè)迭代中執(zhí)行的是 setTimeout(..,0),所有的回調(diào)函數(shù)依然是在勛魂結(jié)束后才會(huì)執(zhí)行,因此每次都輸出6.根據(jù)作用域的工作原理,實(shí)際情況是盡管循環(huán)中的五個(gè)函數(shù)是在各個(gè)迭代中分別定義的,但是它們都是被封閉在一個(gè)共享的全局作用域中,因此實(shí)際上只有一個(gè) i。
再看下一個(gè)代碼,給上一代碼加入更多的詞法作用域,且要加入實(shí)質(zhì)內(nèi)容才能起作用。
for(var i=1; i<=5; i++){ (function() { var j = i; setTimeout(function timer(){ console.log(j); },j*1000) })(); }
現(xiàn)在就能正常分別輸出數(shù)字1~5,每秒一次,每次一個(gè)。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/80306.html
摘要:閉包引起的內(nèi)存泄漏總結(jié)從理論的角度將由于作用域鏈的特性中所有函數(shù)都是閉包但是從應(yīng)用的角度來說只有當(dāng)函數(shù)以返回值返回或者當(dāng)函數(shù)以參數(shù)形式使用或者當(dāng)函數(shù)中自由變量在函數(shù)外被引用時(shí)才能成為明確意義上的閉包。 文章同步到github js的閉包概念幾乎是任何面試官都會(huì)問的問題,最近把閉包這塊的概念梳理了一下,記錄成以下文章。 什么是閉包 我先列出一些官方及經(jīng)典書籍等書中給出的概念,這些概念雖然...
摘要:當(dāng)在中調(diào)用匿名函數(shù)時(shí),它們用的都是同一個(gè)閉包,而且在這個(gè)閉包中使用了和的當(dāng)前值的值為因?yàn)檠h(huán)已經(jīng)結(jié)束,的值為。最好將閉包當(dāng)作是一個(gè)函數(shù)的入口創(chuàng)建的,而局部變量是被添加進(jìn)這個(gè)閉包的。 閉包不是魔法 這篇文章使用一些簡(jiǎn)單的代碼例子來解釋JavaScript閉包的概念,即使新手也可以輕松參透閉包的含義。 其實(shí)只要理解了核心概念,閉包并不是那么的難于理解。但是,網(wǎng)上充斥了太多學(xué)術(shù)性的文章,對(duì)于...
摘要:一言以蔽之,閉包,你就得掌握。當(dāng)函數(shù)記住并訪問所在的詞法作用域,閉包就產(chǎn)生了。所以閉包才會(huì)得以實(shí)現(xiàn)。從技術(shù)上講,這就是閉包。執(zhí)行后,他的內(nèi)部作用域并不會(huì)消失,函數(shù)依然保持有作用域的閉包。 網(wǎng)上總結(jié)閉包的文章已經(jīng)爛大街了,不敢說筆者這篇文章多么多么xxx,只是個(gè)人理解總結(jié)。各位看官瞅瞅就好,大神還希望多多指正。此篇文章總結(jié)與《JavaScript忍者秘籍》 《你不知道的JavaScri...
摘要:權(quán)威指南第版中閉包的定義函數(shù)對(duì)象可以通過作用域鏈相互關(guān)聯(lián)起來,函數(shù)體內(nèi)部的變量都可以保存在函數(shù)作用域內(nèi),這種特性在計(jì)算機(jī)科學(xué)文獻(xiàn)中成為閉包。循環(huán)中的閉包使用閉包時(shí)一種常見的錯(cuò)誤情況是循環(huán)中的閉包,很多初學(xué)者都遇到了這個(gè)問題。 閉包簡(jiǎn)介 閉包是JavaScript的重要特性,那么什么是閉包? 《JavaScript高級(jí)程序設(shè)計(jì)(第3版)》中閉包的定義: 閉包就是指有權(quán)訪問另一個(gè)函數(shù)中的變...
摘要:注意由于閉包會(huì)額外的附帶函數(shù)的作用域內(nèi)部匿名函數(shù)攜帶外部函數(shù)的作用域,因此,閉包會(huì)比其它函數(shù)多占用些內(nèi)存空間,過度的使用可能會(huì)導(dǎo)致內(nèi)存占用的增加。 作用域和作用域鏈?zhǔn)莏avascript中非常重要的特性,對(duì)于他們的理解直接關(guān)系到對(duì)于整個(gè)javascript體系的理解,而閉包又是對(duì)作用域的延伸,也是在實(shí)際開發(fā)中經(jīng)常使用的一個(gè)特性,實(shí)際上,不僅僅是javascript,在很多語言中都...
摘要:也許最好的理解是閉包總是在進(jìn)入某個(gè)函數(shù)的時(shí)候被創(chuàng)建,而局部變量是被加入到這個(gè)閉包中。在函數(shù)內(nèi)部的函數(shù)的內(nèi)部聲明函數(shù)是可以的可以獲得不止一個(gè)層級(jí)的閉包。 前言 總括 :這篇文章使用有效的javascript代碼向程序員們解釋了閉包,大牛和功能型程序員請(qǐng)自行忽略。 譯者 :文章寫在2006年,可直到翻譯的21小時(shí)之前作者還在完善這篇文章,在Stackoverflow的How do Java...
閱讀 2772·2021-10-14 09:42
閱讀 827·2021-10-11 10:57
閱讀 773·2019-08-30 15:54
閱讀 1914·2019-08-30 13:50
閱讀 1686·2019-08-30 11:19
閱讀 932·2019-08-29 12:38
閱讀 1425·2019-08-26 11:51
閱讀 1388·2019-08-26 10:48