這兩天在研究閉包,網上一通找,有牛人寫的帖子,有普通人寫的帖子,可是大多沒戳中本小白所糾結的點,並且大多插入了當即執行函數,其實根本不須要的,反而讓人產生了誤解。這裏我用個人方式講解一下閉包。閉包
1.目的:保證局部變量常駐在內存中,且只能經過固定的方式訪問,不能夠被全部人訪問,算起來也算是個只能被指定對象訪問的專用型全局變量。函數
2.實現方式:在函數f1中返回一個內部定義的函數f2,後經過使用返回出來的函數f2來操做f1中定義的局部變量。spa
下面我來從各類刁鑽的角度來舉例詳細說明,包學包會!看完例子之後再看上面說的目的和實現方式就會有種豁然開朗的感受了!code
round 1:對象
function add() { var x = 0; return function () { return ++x; } }; /*此處的add()的括號和function add()的括號表達的意思是徹底不一樣的, 在此處add表示上 面定義的函數,add()表示執行一次上面定義的函 數,這一點很關鍵!執行一次的結果就是返回了函數 function () {return ++x;},可是請注意!這裏返回的僅僅是函數本 身,也就是此時函數還沒有執行,故此時x=0*/ var temp=add(); //執行一次返回的函數,++x,此時x=1 temp(); //再次執行一次返回的函數,此時x=2,且輸出了函數的返回值2,能夠在控制檯中看到 console.log(temp());
這就完成了閉包了,add函數中的x常駐內存,且我能夠在add函數外部經過調用它返回的函數來操做這個x,若是看懂了下面能夠不看,若是看了其餘帖子有一些其餘的異或好比當即執行函數之類的能夠看看下面的,你很快就不會疑惑了!blog
round 2:內存
//此處temp表示函數add函數自己,可是還沒有執行。 var temp = function add() { var x = 0; return function () { return ++x; } }; //執行temp函數,返回函數 function () {return ++x;},但還沒有執行該函數,故x=0 var temp1 = temp(); //執行temp1,此時執行了一次function () {return ++x;},故x=1 temp1(); //再次執行一次function () {return ++x;},此時x=2,且輸出到了控制檯 console.log(temp1());
這一回合是爲下面的當即執行函數作鋪墊,下面當即執行函數版本隆重登場!噹噹噹當!io
round 3:console
/*仔細看,此處爲(fucntion add(){})(),此處執行了當即執行函數,也就是說返回給temp的與round2返回的add函數自己不一樣,而是返回的 function () {return ++x;}*/ var temp = (function add() { var x = 0; return function () { return ++x; } })(); //瓜熟蒂落的,這裏直接執行temp,就是執行了function () {return ++x;},故x=1 temp(); //同理x=2 console.log(temp());
通過上面三個例子的講解想必你已經心中有數了,可是確定仍是存在疑惑的,好比說round1中var temp=add();,我不把add()的結果賦給temp直接執行行不行?答案是否認的,有一點必定要認知清楚,函數是對象,這一點相當重要,不然將會走入誤區。下面舉例說明:function
這個是round1的改版:
function add() { var x = 0; return function () { return ++x; } }; console.log(add()());//輸出1 console.log(add()());//輸出1
爲何會這樣呢?關鍵點在於函數是對象,上面實行了兩次add()(),在這兩次中,add()返回的對象是不同的,因此他們各自再執行add()()就是爲各自的局部變量x加1,因此才兩次都輸出1,假如改一下
function add() { var x = 0; return function () { return ++x; } }; var temp1 = add(); var temp2 = add(); console.log(temp1());//輸出1 console.log(temp1());//輸出2 console.log(temp2());//輸出1 console.log(temp2());//輸出2
這樣是否是就明白了,同理add函數也不能寫成下面這種形式:
function add() { var x = 0; return (function () { return ++x; })() };
不然返回的只是一個常量而不是一個對象了。但願這篇文章能給跟我同樣在摸索閉包的小白一點啓發,嘿嘿嘿