這兩天在研究閉包,網上一通找,有牛人寫的帖子,有普通人寫的帖子,但是大多沒戳中本小白所糾結的點,而且大多插入了立即執行函式,其實根本不需要的,反而讓人產生了誤解,這里我用我的方式講解一下閉包,
1.目的:保證區域變數常駐在記憶體中,且只能通過固定的方式訪問,不可以被所有人訪問,算起來也算是個只能被指定物件訪問的專用型全域變數,
2.實作方式:在函式f1中回傳一個內部定義的函式f2,后通過使用回傳出來的函式f2來操作f1中定義的區域變數,
下面我來從各種刁鉆的角度來舉例詳細說明,包學包會!看完例子以后再看上面說的目的和實作方式就會有種豁然開朗的感覺了!
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,如果看懂了下面可以不看,如果看了其他帖子有一些其他的異或比如立即執行函式之類的可以看看下面的,你很快就不會疑惑了!
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());
這一回合是為下面的立即執行函式做鋪墊,下面立即執行函式版本隆重登場!當當當當!
round 3:
/*仔細看,此處為(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直接執行行不行?答案是否定的,有一點一定要認知清楚,函式是物件,這一點至關重要,否則將會走入誤區,下面舉例說明:
這個是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; })() };
否則回傳的只是一個常量而不是一個物件了,希望這篇文章能給跟我一樣在摸索閉包的小白一點啟發,嘿嘿嘿
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/180436.html
標籤:JavaScript
上一篇:vue創建組件的幾種方法
