javascript 閉包及其解決
閉包
是指在一個函數中聲明一個函數,在外部函數結束的時候返回內部函數的引用,那麽在執行外部函數的時候就會
產生一個內部函數的引用,因為外部函數執行完成,理論上外部函數的ao的引用是應該被刪除或者說釋放的。
但因為有了內部函數的引用,這個內部函數在聲明的時候就已經指向了外部函數的ao以及go,所以,即使外部函數
ao的引用已經釋放,由於內部函數被保存在了外部,導致外部函數申明與執行所產生的ao被保留下來。
<body> <script type="text/javascript"> function a(){ function b(){var bbb = 234; consloet.log(aaa); };
var a = 123 return b; } var golb = 100; var demo = a(); demo(); </script> </body>
此例的輸出結果是:123
按原來的理解,b函數中是沒有a這個變量的,正常如果沒有外部的a函數,就會報錯 a is not define
但是這裏,由於在a執行完的時候,把b的引用保存在了函數a之外,而b這個函數在聲明的時候,它的scope chain仍然和a執行是同一個,
即:0:aAO;1:GO,就是把a中的執行上下文保存在了b函數中。在執行函數b的時候回生成一個bAO放在scope chain的0位置,執行完的
時候刪除這個bAO,而在1、2位置的0:aAO;1:GO被永久的保留了下來。
aAO中是由a = 123這個變量的,故而最終的結果是打印出a的值!~
這 就是閉包!
**註意點**------當內部函數被保存到外部時,將會生成閉包。閉包會導致原有scope chain(作用域鏈)不釋放,造成內存泄漏
內存泄漏:由於內存一直占用,導致可用內存空間減小,感覺就像內存泄漏了一樣,就叫內存泄漏了~~!會導致加載非常慢!!
scope chain 中的沒生成一個新的ao,必然繼承外部函數產生的ao與go,這裏的繼承是指指向了原來那個AO、GO,而不是生成一個一模一樣的
ex:
<body> <script type="text/javascript"> function text(){ var num = 100; function b(){ num ++; console.log(num); } function b(){ num --; console.log(num); } return [a,b]; } var myArr = text(); myArr[0](); myArr[1](); </script> </body>
輸出的結果是:101 100
而不是101 99,註意其中的區別!
所以再修改來自外部函數的ao時,是修改的同一個AO
ex:
<body> <script type="text/javascript"> function a(){ var num = 100; function b(){ num ++; console.log(num); } return b; } var demo = a(); demo(); demo(); </script> </body>
此例的結果是:101
102
有累加的效果
閉包的作用:1實現共有變量----->函數累加器
2可以做緩存(存儲結構)----->eater
3可以實現封裝,屬性私有化------>Person();
4模塊化開發,防止汙染全局變量
ex: 實現共有變量----->函數累加器
<body> <script type="text/javascript"> function add(){ var count = 0; function demo(){ count ++; consloet.log(count); }; return demo; } var counter = add(); counter(); counter(); counter(); counter(); counter(); counter(); counter(); counter(); </script> </body>
輸出結果: 1 2 3 4 5 6 7
ex:可以做緩存(存儲結構)----->eater 3
<body> <script type="text/javascript"> function eater(){ var food = ""; var obj = { eat : function(){ console.log("i am eating!" + food); food = ""; }, push : function(myfood){ food = myfood; } } return obj; } var demo = a(); erter1.push(‘banana‘); eater1.eat(); </script> </body>
輸出結果; i am eating banana
其中實際有兩個過程,一個把banana放入myfood,第二個過程才是打印 i am eating banana
javascript 閉包及其解決