輕松理解JavaScript閉包
摘要
閉包機(jī)制是JavaScript的重點(diǎn)和難點(diǎn),本文希望能幫助大家輕松的學(xué)習(xí)閉包
一、什么是閉包?
閉包就是可以訪問另一個(gè)函數(shù)作用域中變量的函數(shù)。
下面列舉出常見的閉包實(shí)現(xiàn)方式,以例子講解閉包概念
function f1(){
var n=999;
nAdd=function(){n+=1}
function f2(){
alert(n);
}
return f2;
}
var result=f1();
result(); // 999
nAdd();
result(); // 1000
f1是f2的父函數(shù),而f2被賦給了一個(gè)全局變量(return的值),這導(dǎo)致f2始終在內(nèi)存中,而f2的存在依賴于f1,因此f1也始終在內(nèi)存中,不會(huì)在調(diào)用結(jié)束后,被垃圾回收機(jī)制(garbage collection)回收,這便形成了閉包。
因此,可以這么理解。閉包機(jī)制就是,如果A函數(shù)引用了另一個(gè)函數(shù)B的變量,但是B返回后A仍沒有返回,仍存在,因?yàn)锳的引用,所以B的所有局部變量并不會(huì)隨B退出而注銷,會(huì)一直存在,直到A注銷。此時(shí)A就是閉包。
二、閉包的this指針
閉包通常在全局環(huán)境調(diào)用的,所以this通常指向window,具體情況還是需要視執(zhí)行環(huán)境而言,總之this指向執(zhí)行環(huán)境。
若需要閉包的this指向閉包的包含對(duì)象,則需要將包含對(duì)象的this作為變量傳進(jìn)閉包。
三、使用閉包的注意點(diǎn)
- 由于閉包會(huì)使得函數(shù)中的變量都被保存在內(nèi)存中,內(nèi)存消耗很大,所以不能濫用閉包,否則會(huì)造成網(wǎng)頁的性能問題,在IE中可能導(dǎo)致內(nèi)存泄露。解決方法是,在退出函數(shù)之前,將不使用的局部變量全部刪除。
- 閉包會(huì)在父函數(shù)外部,改變父函數(shù)內(nèi)部變量的值。所以,如果你把父函數(shù)當(dāng)作對(duì)象(object)使用,把閉包當(dāng)作它的公用方法(Public Method),把內(nèi)部變量當(dāng)作它的私有屬性(private value),這時(shí)一定要小心,不要隨便改變父函數(shù)內(nèi)部變量的值。
四、解決一道閉包常見面試題
問題:
function onMyLoad(){
/*
拋出問題:
此題的目的是想每次點(diǎn)擊對(duì)應(yīng)目標(biāo)時(shí)彈出對(duì)應(yīng)的數(shù)字下標(biāo) 0~4,但實(shí)際是無論點(diǎn)擊哪個(gè)目標(biāo)都會(huì)彈出數(shù)字5
問題所在:
arr 中的每一項(xiàng)的 onclick 均為一個(gè)函數(shù)實(shí)例(Function 對(duì)象),這個(gè)函數(shù)實(shí)例也產(chǎn)生了一個(gè)閉包域,
這個(gè)閉包域引用了外部閉包域的變量,其 function scope 的 closure 對(duì)象有個(gè)名為 i 的引用,
外部閉包域的私有變量?jī)?nèi)容發(fā)生變化,內(nèi)部閉包域得到的值自然會(huì)發(fā)生改變
*/
var arr = document.getElementsByTagName("p");
for(var i = 0; i < arr.length;i++){
arr[i].onclick = function(){
alert(i);
}
}
}
解決方法
1、在外面再加一層函數(shù),將i作為函數(shù)參數(shù)傳進(jìn)來,這樣每次保存的是函數(shù)內(nèi)部的變量,與外部i不是同一個(gè)內(nèi)存空間,而每次調(diào)用函數(shù)都會(huì)生成一個(gè)局部變量,所以可以保證每次保存的值互不影響。
for(var i = 0; i<arr.length;i++){
arr[i].onclick = (function(arg){
return function () {
alert(arg);
}
})(i);
}
2、用ES6新特let,將for循環(huán)的var i改成let i,這樣當(dāng)前的i只在本輪循環(huán)有效,所以每一次循環(huán)的i其實(shí)都是一個(gè)新的變量。你可能會(huì)問,如果每一輪循環(huán)的變量i都是重新聲明的,那它怎么知道上一輪循環(huán)的值,從而計(jì)算出本輪循環(huán)的值?這是因?yàn)?JavaScript 引擎內(nèi)部會(huì)記住上一輪循環(huán)的值,初始化本輪的變量i時(shí),就在上一輪循環(huán)的基礎(chǔ)上進(jìn)行計(jì)算。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來一定的幫助,同時(shí)也希望多多支持腳本之家!
- 通俗易懂地解釋JS中的閉包
- JS繼承與閉包及JS實(shí)現(xiàn)繼承的三種方式
- 淺談JavaScript作用域和閉包
- JS閉包的幾種常見形式實(shí)例詳解
- JS實(shí)現(xiàn)閉包中的沙箱模式示例
- JavaScript閉包的簡(jiǎn)單應(yīng)用
- 通過示例徹底搞懂js閉包
- JavaScript閉包和回調(diào)詳解
- 淺談JS封閉函數(shù)、閉包、內(nèi)置對(duì)象
- JavaScript閉包_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- 深入理解Javascript中的作用域鏈和閉包
- JS閉包可被利用的常見場(chǎng)景小結(jié)
- 利用js的閉包原理做對(duì)象封裝及調(diào)用方法
- javascript閉包功能與用法實(shí)例分析
- JavaScript中閉包的詳解
- JS閉包用法實(shí)例分析
- 圖解Javascript——作用域、作用域鏈、閉包
- js中的閉包學(xué)習(xí)心得
相關(guān)文章
JS利用時(shí)間戳倒計(jì)時(shí)的實(shí)現(xiàn)示例
這篇文章主要介紹了JS利用時(shí)間戳倒計(jì)時(shí)的實(shí)現(xiàn)示例,本文將提供代碼示例和詳細(xì)的步驟,幫助你實(shí)現(xiàn)一個(gè)簡(jiǎn)單而實(shí)用的時(shí)間戳倒計(jì)時(shí),感興趣的可以了解一下2023-12-12
利用JavaScript實(shí)現(xiàn)簡(jiǎn)單的網(wǎng)頁時(shí)鐘
這篇文章主要介紹了利用JavaScript實(shí)現(xiàn)簡(jiǎn)單的網(wǎng)頁時(shí)鐘,主要使用了js的日期對(duì)象,實(shí)現(xiàn)的時(shí)候先創(chuàng)建一個(gè)日期對(duì)象,并進(jìn)行網(wǎng)頁布局,對(duì)時(shí)間獲取之后將時(shí)間填入對(duì)應(yīng)的標(biāo)簽內(nèi)。然后使用多線程實(shí)現(xiàn)時(shí)鐘的變動(dòng),需要的朋友可以參考一下2022-02-02
關(guān)于laydate.js加載laydate.css路徑錯(cuò)誤問題解決
日期時(shí)間選擇插件 laydate.js相信對(duì)大家來說都不陌生,這篇文章主要給大家介紹了關(guān)于laydate.js加載laydate.css路徑錯(cuò)誤問題解決的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起看看吧。2017-12-12
原生JS實(shí)現(xiàn)點(diǎn)擊數(shù)字小游戲
這篇文章主要為大家詳細(xì)介紹了原生JS實(shí)現(xiàn)點(diǎn)擊數(shù)字小游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-04-04
移動(dòng)端網(wǎng)頁開發(fā)調(diào)試神器Eruda的介紹與使用技巧
在日常的移動(dòng)端開發(fā)時(shí),一般都是試用chrome瀏覽器的移動(dòng)端模式進(jìn)行開發(fā)和調(diào)試,只有在chrome調(diào)試完成,而最近發(fā)現(xiàn)了一個(gè)新的調(diào)試方法,所以這篇文章主要給大家介紹了關(guān)于移動(dòng)端網(wǎng)頁開發(fā)調(diào)試神器Eruda的基本資料,以及其使用的一些技巧,需要的朋友可以參考下。2017-10-10
openlayers4實(shí)現(xiàn)點(diǎn)動(dòng)態(tài)擴(kuò)散
這篇文章主要為大家詳細(xì)介紹了openlayers4實(shí)現(xiàn)的點(diǎn)動(dòng)態(tài)擴(kuò)散,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-08-08
對(duì) lightbox JS 圖片控件進(jìn)行了一下改造, 使其他支持復(fù)雜的圖片說明
如果要為圖片添加詳細(xì)的圖片說明,并為圖片的說明設(shè)置一些格式,如字體的大小、顏色等,那么使用 title 這個(gè)屬性來設(shè)置這些說明信息是沒辦法實(shí)現(xiàn)的。2010-03-03

