色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁(yè)技術(shù)文章
文章詳情頁(yè)

帶你一分鐘理解 JavaScript 閉包

瀏覽:23日期:2023-11-18 11:56:31
 什么是閉包?

先看一段代碼:

function a(){ var n = 0; function inc() {n++;console.log(n); } inc(); inc(); }a(); //控制臺(tái)輸出1,再輸出2

簡(jiǎn)單吧。再來(lái)看一段代碼:

function a(){ var n = 0; this.inc = function () {n++; console.log(n); };}var c = new a();c.inc(); //控制臺(tái)輸出1c.inc(); //控制臺(tái)輸出2

簡(jiǎn)單吧。

什么是閉包?這就是閉包!

帶你一分鐘理解 JavaScript 閉包

有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域內(nèi)變量的函數(shù)都是閉包。這里 inc 函數(shù)訪問(wèn)了構(gòu)造函數(shù) a 里面的變量 n,所以形成了一個(gè)閉包。

再來(lái)看一段代碼:

function a(){ var n = 0; function inc(){ n++;console.log(n); } return inc;}var c = a();c(); //控制臺(tái)輸出1c(); //控制臺(tái)輸出2

看看是怎么執(zhí)行的:

var c = couter(),這一句 couter()返回的是函數(shù) inc,那這句等同于 var c = inc;

c(),這一句等同于 inc(); 注意,函數(shù)名只是一個(gè)標(biāo)識(shí)(指向函數(shù)的指針),而()才是執(zhí)行函數(shù)。

后面三句翻譯過(guò)來(lái)就是: var c = inc; inc(); inc();,跟第一段代碼有區(qū)別嗎? 沒(méi)有。

什么是閉包?這就是閉包!

所有的教科書(shū)教程上都喜歡用最后一段來(lái)說(shuō)明閉包,但我覺(jué)得這將問(wèn)題復(fù)雜化了。這里面返回的是函數(shù)名,沒(méi)看過(guò)譚浩強(qiáng)C/C++程序設(shè)計(jì)的同學(xué)可能一下子沒(méi)反應(yīng)出帶不帶()的區(qū)別,也就是說(shuō)這種寫(xiě)法自帶一個(gè)陷阱。雖然這種寫(xiě)法更顯高大上,但我還是喜歡將問(wèn)題單一化,看看代碼 1 和代碼 2,你還會(huì)糾結(jié)函數(shù)的調(diào)用,你會(huì)糾結(jié) n 的值嗎?

帶你一分鐘理解 JavaScript 閉包

 為啥要這樣寫(xiě)?

我們知道,js的每個(gè)函數(shù)都是一個(gè)個(gè)小黑屋,它可以獲取外界信息,但是外界卻無(wú)法直接看到里面的內(nèi)容。將變量 n 放進(jìn)小黑屋里,除了 inc 函數(shù)之外,沒(méi)有其他辦法能接觸到變量 n,而且在函數(shù) a 外定義同名的變量 n 也是互不影響的,這就是所謂的增強(qiáng)“封裝性”。

而之所以要用 return 返回函數(shù)標(biāo)識(shí) inc,是因?yàn)樵?a 函數(shù)外部無(wú)法直接調(diào)用 inc 函數(shù),所以 return inc 與外部聯(lián)系起來(lái),代碼 2 中的 this 也是將 inc 與外部聯(lián)系起來(lái)而已。

帶你一分鐘理解 JavaScript 閉包

 常見(jiàn)的陷阱

看看這個(gè):

function createFunctions(){ var result = new Array(); for (var i=0; i < 10; i++){result[i] = function(){ return i;}; } return result;}var funcs = createFunctions();for (var i=0; i < funcs.length; i++){ console.log(funcs[i]());}

乍一看,以為輸出 0~9 ,萬(wàn)萬(wàn)沒(méi)想到輸出10個(gè)10?

這里的陷阱就是:函數(shù)帶()才是執(zhí)行函數(shù)! 單純的一句 var f = function() { alert(‘Hi’); }; 是不會(huì)彈窗的,后面接一句 f(); 才會(huì)執(zhí)行函數(shù)內(nèi)部的代碼。上面代碼翻譯一下就是:

var result = new Array(), i;result[0] = function(){ return i; }; //沒(méi)執(zhí)行函數(shù),函數(shù)內(nèi)部不變,不能將函數(shù)內(nèi)的i替換!result[1] = function(){ return i; }; //沒(méi)執(zhí)行函數(shù),函數(shù)內(nèi)部不變,不能將函數(shù)內(nèi)的i替換!...result[9] = function(){ return i; }; //沒(méi)執(zhí)行函數(shù),函數(shù)內(nèi)部不變,不能將函數(shù)內(nèi)的i替換!i = 10;funcs = result;result = null;console.log(i); // funcs[0]()就是執(zhí)行 return i 語(yǔ)句,就是返回10console.log(i); // funcs[1]()就是執(zhí)行 return i 語(yǔ)句,就是返回10...console.log(i); // funcs[9]()就是執(zhí)行 return i 語(yǔ)句,就是返回10

為什么只垃圾回收了 result,但卻不收了 i 呢? 因?yàn)?i 還在被 function 引用著啊。好比一個(gè)餐廳,盤(pán)子總是有限的,所以服務(wù)員會(huì)去巡臺(tái)回收空盤(pán)子,但還裝著菜的盤(pán)子他怎么敢收? 當(dāng)然,你自己手動(dòng)倒掉了盤(pán)子里面的菜(=null),那盤(pán)子就會(huì)被收走了,這就是所謂的內(nèi)存回收機(jī)制。

至于 i 的值怎么還能保留,其實(shí)從文章開(kāi)頭一路讀下來(lái),這應(yīng)該沒(méi)有什么可以糾結(jié)的地方。盤(pán)子里面的菜,吃了一塊不就應(yīng)該少一塊嗎?

 總結(jié)一下

閉包就是一個(gè)函數(shù)引用另外一個(gè)函數(shù)的變量,因?yàn)樽兞勘灰弥圆粫?huì)被回收,因此可以用來(lái)封裝一個(gè)私有變量。這是優(yōu)點(diǎn)也是缺點(diǎn),不必要的閉包只會(huì)徒增內(nèi)存消耗!另外使用閉包也要注意變量的值是否符合你的要求,因?yàn)樗拖褚粋€(gè)靜態(tài)私有變量一樣。閉包通常會(huì)跟很多東西混搭起來(lái),接觸多了才能加深理解,這里只是開(kāi)個(gè)頭說(shuō)說(shuō)基礎(chǔ)性的東西。

標(biāo)簽: JavaScript
相關(guān)文章:
主站蜘蛛池模板: 国产成人www免费人成看片 | 美国免费一级片 | 国产午夜人做人视频羞羞 | 国产成人综合久久亚洲精品 | 欧美性f| 亚州黄色网址 | 国产精品久久国产精品99 | 国产精品久久久亚洲 | 欧美成人免费在线 | 在线成人aa在线看片 | 亚洲精品第五页中文字幕 | 性欧美videofree另类17 | 免费a级毛片无码 | 亚洲精品国产福利片 | 精品国产爱久久 | 国产亚洲高清在线精品99 | 欧美日韩一级二级三级 | 欧美精品在线免费观看 | 成年人在线观看视频免费 | 波多野结衣一区二区三区高清在线 | 国产大乳孕妇喷奶水在线观看 | 国产日韩一区二区三区在线观看 | 久久厕所精品国产精品亚洲 | 国内精品久久久久久中文字幕 | 一区二区三区在线 | 网站 | 狠狠色综合网站久久久久久久 | 99精品视频在线观看免费播放 | 亚洲综合p | 亚洲视频免费在线看 | 国产成人久久精品二区三区牛 | 国产一级视频免费 | 国产精品一区二区在线观看 | 久草综合网 | 欧美久草 | 国产在线不卡午夜精品2021 | 国产成人精品一区二区免费 | 日韩性视频网站 | 欧美成人精品高清在线观看 | 美女作爱网站 | 久久视频精品36线视频在线观看 | 在线观看99 |