您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關(guān)Javascript閉包使用場(chǎng)景的原理分析的內(nèi)容。小編覺得挺實(shí)用的,因此分享給大家做個(gè)參考,一起跟隨小編過來看看吧。
Javascript
中,只有函數(shù)內(nèi)部的子函數(shù)才能讀取局部變量,閉包就是能夠讀取其他函數(shù)內(nèi)部變量的函數(shù)。
比如下面的代碼:
function f1() { var n = 999; function f2() { console.log(n); } return f2; } var result = f1(); result();//999
函數(shù)f2就被包括在函數(shù)f1內(nèi)部,這時(shí)f1內(nèi)部的所有局部變量,對(duì)f2都是可見的。但是反過來就不行,f2內(nèi)部的局部變量,對(duì)f1就是不可見的。
這就是Javascript
語言特有的"鏈?zhǔn)阶饔糜?quot;結(jié)構(gòu)(chain scope
),子對(duì)象會(huì)一級(jí)一級(jí)地向上尋找所有父對(duì)象的變量。所以,父對(duì)象的所有變量,對(duì)子對(duì)象都是可見的,反之則不成立。
既然f2可以讀取f1中的局部變量,那么只要把f2作為返回值,就可以在f1外部讀取它的內(nèi)部變量了。
原生的setTimeout
傳遞的第一個(gè)函數(shù)不能帶參數(shù),通過閉包可以實(shí)現(xiàn)傳參效果。
function f1(a) { function f2() { console.log(a); } return f2; } var fun = f1(1); setTimeout(fun,1000);//一秒之后打印出1
定義行為,然后把它關(guān)聯(lián)到某個(gè)用戶事件上(點(diǎn)擊或者按鍵)。代碼通常會(huì)作為一個(gè)回調(diào)(事件觸發(fā)時(shí)調(diào)用的函數(shù))綁定到事件。
比如下面這段代碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>測(cè)試</title> </head> <body> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-12">12</a> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-20">20</a> <a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" id="size-30">30</a> <script type="text/javascript"> function changeSize(size){ return function(){ document.body.style.fontSize = size + 'px'; }; } var size12 = changeSize(12); var size14 = changeSize(20); var size16 = changeSize(30); document.getElementById('size-12').onclick = size12; document.getElementById('size-20').onclick = size14; document.getElementById('size-30').onclick = size16; </script> </body> </html>
當(dāng)點(diǎn)擊數(shù)字時(shí),字體也會(huì)變成相應(yīng)的大小。
在事件被觸發(fā)n秒后再執(zhí)行回調(diào),如果在這n秒內(nèi)又被觸發(fā),則重新計(jì)時(shí)。
實(shí)現(xiàn)的關(guān)鍵就在于setTimeOut
這個(gè)函數(shù),由于還需要一個(gè)變量來保存計(jì)時(shí),考慮維護(hù)全局純凈,可以借助閉包來實(shí)現(xiàn)。
如下代碼所示:
/* * fn [function] 需要防抖的函數(shù) * delay [number] 毫秒,防抖期限值 */ function debounce(fn,delay){ let timer = null //借助閉包 return function() { if(timer){ clearTimeout(timer) //進(jìn)入該分支語句,說明當(dāng)前正在一個(gè)計(jì)時(shí)過程中,并且又觸發(fā)了相同事件。所以要取消當(dāng)前的計(jì)時(shí),重新開始計(jì)時(shí) timer = setTimeOut(fn,delay) }else{ timer = setTimeOut(fn,delay) // 進(jìn)入該分支說明當(dāng)前并沒有在計(jì)時(shí),那么就開始一個(gè)計(jì)時(shí) } } }
如下面代碼:用js創(chuàng)建一個(gè)計(jì)數(shù)器
方法1:
function f1() { var sum = 0; var obj = { inc:function () { sum++; return sum; } }; return obj; } let result = f1(); console.log(result.inc());//1 console.log(result.inc());//2 console.log(result.inc());//3
在返回的對(duì)象中,實(shí)現(xiàn)了一個(gè)閉包,該閉包攜帶了局部變量x,并且,從外部代碼根本無法訪問到變量x。
方法2:
function f1() { var sum = 0; function f2() { sum++; return f2; } f2.valueOf = function () { return sum; }; f2.toString = function () { return sum+''; }; return f2; } //執(zhí)行函數(shù)f1,返回的是函數(shù)f2 console.log(+f1());//0 console.log(+f1()())//1 console.log(+f1()()())//2
所有js數(shù)據(jù)類型都擁有valueOf
和toString
這兩個(gè)方法,null
除外
valueOf()
方法:返回指定對(duì)象的原始值。
toString()
方法:返回對(duì)象的字符串表示。
在數(shù)值運(yùn)算中,優(yōu)先調(diào)用了valueOf
,字符串運(yùn)算中,優(yōu)先調(diào)用toString
sum+' '
是一個(gè)字符串類型的數(shù)據(jù)
感謝各位的閱讀!關(guān)于“Javascript閉包使用場(chǎng)景的原理分析”這篇文章就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,讓大家可以學(xué)到更多知識(shí),如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到吧!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。