云天视角-浅谈闭包
一、現(xiàn)狀
閉包是jser繞不過(guò)的坎,一直在都在說(shuō),套用 simpson 的話來(lái)說(shuō):JavaScript中閉包無(wú)處不在,你只需要能夠識(shí)別并擁抱它。
閉包是基于詞法作用域書寫代碼時(shí)的自然結(jié)果,你甚至不需要為了利用它們而有意識(shí)的去創(chuàng)建閉包。閉包的創(chuàng)建和使用在你的代碼中隨處可見(jiàn)。你缺少的只是根據(jù)你的意愿來(lái)識(shí)別、擁抱和影響閉包的思維環(huán)境
二、什么是閉包(closure)
當(dāng)函數(shù)可以記住并訪問(wèn)所在的詞法作用域時(shí),就產(chǎn)生了閉包。即使函數(shù)是在當(dāng)前詞法作用域之外執(zhí)行 --《你不知道的js》(上卷) 閉包是指有權(quán)訪問(wèn)另一個(gè)函數(shù)作用域中的變量的函數(shù) --《JavaScript高級(jí)程序設(shè)計(jì)》先來(lái)看一個(gè)例子:
例子1:
這是閉包嗎?
這個(gè)代碼從技術(shù)上來(lái)說(shuō)是,但也可以說(shuō)不是。準(zhǔn)確的來(lái)說(shuō)bar()對(duì)a的引用的方法是詞法作用域的查找規(guī)則。我們?cè)賮?lái)看:
例子2:
在例2中,我們將bar()函數(shù)本身當(dāng)做一個(gè)值類型進(jìn)行傳遞,函數(shù)bar()能夠訪問(wèn)foo()的內(nèi)部作用域。在這個(gè)例子中,它在自己定義的詞法作用域以外的地方執(zhí)行。
三、怎么形成的
要了解清楚,得先了解幾個(gè)概念
- 作用域鏈(scope chain)
- 詞法作用域
詞法作用域
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境。這個(gè)環(huán)境可以訪問(wèn)外部環(huán)境,以此類推。每個(gè)環(huán)境能訪問(wèn)到的標(biāo)識(shí)符集合,稱之為 作用域,也就是詞法作用域。
作用域鏈(scope chain)
將作用域一層一層的嵌套,就形成了作用域鏈
如下,通常我們都希望foo()在執(zhí)行完成以后,整個(gè)的內(nèi)部作用域都被銷毀。因?yàn)槲覀冎酪嬗欣厥諜C(jī)制用來(lái)釋放不再使用的內(nèi)存空間。由于看上去foo()的內(nèi)容不會(huì)再被使用,所以很自然的想到會(huì)對(duì)其回收。但是,事實(shí)上內(nèi)部作用域依然存在
var globalVar = 10; function foo() {var fooVar = 20;function bar() {var barVar = 30;return globalVar + fooVar + barVar;}return bar; } var baz = foo(); baz();如上,用一張圖表示
這個(gè)作用域鏈在函數(shù)創(chuàng)建的時(shí)候就保存起來(lái)了。
baz()函數(shù)在執(zhí)行的時(shí)候(執(zhí)行bar()函數(shù)),將當(dāng)前的變量對(duì)象(由于當(dāng)前的環(huán)境是函數(shù),所以將其活動(dòng)對(duì)象作為變量對(duì)象)添加到作用域鏈的前端。此時(shí),由于bar()在執(zhí)行,而作用域鏈也存在,所以可以在作用域鏈上進(jìn)行查找,去訪問(wèn)foo()的變量。
四、閉包的應(yīng)用場(chǎng)景有哪些
- 創(chuàng)建私有變量或函數(shù)
五、閉包的缺點(diǎn)
- 閉包中的值是存在于內(nèi)存中,濫用的話會(huì)導(dǎo)致內(nèi)存消耗過(guò)大
閉包經(jīng)典問(wèn)題
// 函數(shù)作用:希望它返回一個(gè)數(shù)組。該數(shù)組的元素為遍歷的索引值 function hello(){var res = [];for (var i = 0,len = 5;i < len;i++){res[i] = function () {return i;}}return res; }返回的結(jié)果跟我們期待的不一樣,因?yàn)?#xff1a;閉包保存的是整個(gè)變量對(duì)象,而不是每個(gè)變量。
解決方案:
這里,沒(méi)有沒(méi)有把閉包直接賦值給數(shù)組。而是定義了一個(gè)匿名函數(shù),并且將立即執(zhí)行該匿名函數(shù)的結(jié)果賦值給數(shù)組,由于參數(shù)是按值傳遞的,所以會(huì)將當(dāng)前值傳給參數(shù)num。
參考資料:《你不知道的js》(中卷)、《JavaScript高級(jí)程序設(shè)計(jì)》完
總結(jié)
- 上一篇: 13.首页内容展示
- 下一篇: Struts2第十一篇【简单UI标签、数