通過示例徹底搞懂js閉包
例1
function sayHello(name) { var text = 'Hello ' + name; var sayAlert = function() { console.log(text); } sayAlert(); } sayHello("Bob") // 輸出"Hello Bob"
在sayHello()函數(shù)中定義并調(diào)用了sayAlert()函數(shù);sayAlert()作為內(nèi)層函數(shù),可以訪問外層函數(shù)sayHello()中的text變量。
例2
function sayHello2(name) { var text = 'Hello ' + name; // 局部變量 var sayAlert = function() { console.log(text); } return sayAlert; } var say2 = sayHello2("Jane"); say2(); // 輸出"Hello Jane"
例3
function buildList(list) { var result = []; for(var i = 0; i < list.length; i++) { var item = 'item' + list[i]; result.push( function() { console.log(item + ' ' + list[i]); } ); } return result; } var fnlist = buildList([1,2,3]); for (var j = 0; j < fnlist.length; j++) { fnlist[j](); }
得到的結(jié)果:連續(xù)輸出3個(gè)"item3 undefined"
解析:通過執(zhí)行buildList函數(shù),返回了一個(gè)result,那么這個(gè)result存放的是3個(gè)匿名函數(shù)。然而這三個(gè)匿名函數(shù)其實(shí)就是三個(gè)閉包,因?yàn)樗梢栽L問到父函數(shù)的局部變量。所以閉包內(nèi)的保留的i是最終的值為3.所以list[3]肯定是undefined. item變量值為item3.
改成如下代碼:
function buildList(list) { var result = []; for(var i = 0; i < list.length; i++) { var item = 'item' + list[i]; result.push( (function(i) { console.log(item + ' ' + list[i]); })(i) ); } return result; } var fnlist = buildList([1,2,3]);
得到的結(jié)果:
item1 1 item2 2 item3 3
解釋:這兒雖然傳遞了一個(gè)數(shù)組進(jìn)去,但是返回的是三個(gè)自執(zhí)行的函數(shù)。
例4
function newClosure(someNum, someRef) { var anArray = [1,2,3]; var num = someNum; var ref = someRef; return function(x) { num += x; anArray.push(num); console.log('num: ' + num + "; " + 'anArray ' + anArray.toString() + "; " + 'ref.someVar ' + ref.someVar); } } closure1 = newClosure(40, {someVar: "closure 1"}); closure2 = newClosure(1000, {someVar: "closure 2"}); closure1(5); // 打印"num: 45; anArray 1,2,3,45; ref.someVar closure 1" closure2(-10); // 打印"num: 990; anArray 1,2,3,990; ref.someVar closure 2"
每次調(diào)用newClosure()都會(huì)創(chuàng)建獨(dú)立的閉包,它們的局部變量num與ref的值并不相同。
例5
function sayAlice() { var sayAlert = function() { console.log(alice); } var alice = 'Hello Alice'; return sayAlert; } var sayAlice2 = sayAlice(); sayAlice2(); // 輸出"Hello Alice"
alice變量在sayAlert函數(shù)之后定義,這并未影響代碼執(zhí)行。因?yàn)榉祷睾瘮?shù)sayAlice2所指向的閉包會(huì)包含sayAlice()函數(shù)中的所有局部變量,這自然包括了alice變量,因此可以正常打印”Hello Alice”。
例6
function setupSomeGlobals() { var num = 666; gAlertNumber = function() { console.log(num); } gIncreaseNumber = function() { num++; } gSetNumber = function(x) { num = x; } } setupSomeGlobals(); gAlertNumber(); // 輸出666 gIncreaseNumber(); gAlertNumber(); // 輸出667 gSetNumber(5); gAlertNumber(); // 輸出5
解釋:首先gAlertNumber,gIncreaseNumber,gSetNumber是三個(gè)全局變量,并且其三個(gè)值都是匿名函數(shù),然而這三個(gè)匿名函數(shù)本身都是閉包。他們操作的num都是保存在內(nèi)存中的同一個(gè)num,所有會(huì)得出上面的結(jié)果。
以上這篇通過示例徹底搞懂js閉包就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- 通俗易懂地解釋JS中的閉包
- JS繼承與閉包及JS實(shí)現(xiàn)繼承的三種方式
- 淺談JavaScript作用域和閉包
- JS閉包的幾種常見形式實(shí)例詳解
- JS實(shí)現(xiàn)閉包中的沙箱模式示例
- JavaScript閉包的簡單應(yīng)用
- JavaScript閉包和回調(diào)詳解
- 淺談JS封閉函數(shù)、閉包、內(nèi)置對象
- JavaScript閉包_動(dòng)力節(jié)點(diǎn)Java學(xué)院整理
- 深入理解Javascript中的作用域鏈和閉包
- JS閉包可被利用的常見場景小結(jié)
- 利用js的閉包原理做對象封裝及調(diào)用方法
- javascript閉包功能與用法實(shí)例分析
- JavaScript中閉包的詳解
- JS閉包用法實(shí)例分析
- 圖解Javascript——作用域、作用域鏈、閉包
- 輕松理解JavaScript閉包
- js中的閉包學(xué)習(xí)心得
相關(guān)文章
js動(dòng)態(tài)添加onload、onresize、onscroll事件(另類方法)
window 的 onload、onresize、onscroll 事件,跟其他的事件不一樣,它不能用 attachEvent 或 addEventListener 來添加于是本人想了一些另類的方法,需要了解的朋友可以參考下2012-12-12JS Array創(chuàng)建及concat()split()slice()的使用方法
下面小編就為大家?guī)硪黄狫S Array創(chuàng)建及concat()split()slice()的使用方法。小編覺得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2016-06-06js圖片上傳中file、bolb、base64圖片之間的相互轉(zhuǎn)化
這篇文章主要介紹了js圖片上傳中file、bolb、base64圖片之間的相互轉(zhuǎn)化,blob轉(zhuǎn)file,blob轉(zhuǎn)base64,base64轉(zhuǎn)file,使用canvas壓縮圖片,需要的朋友可以參考下2022-05-05Bootstrap學(xué)習(xí)筆記之css組件(3)
這篇文章主要為大家詳細(xì)介紹了bootstrap學(xué)習(xí)筆記中的css組件,感興趣的小伙伴們可以參考一下2016-06-06javascript實(shí)現(xiàn)貪吃蛇小練習(xí)
這篇文章主要為大家詳細(xì)介紹了javascript實(shí)現(xiàn)貪吃蛇的小練習(xí),文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-07-07