觀感度:🌟🌟🌟🌟🌟javascript
口味:冰鎮西瓜html
烹飪時間:20min前端
撩妹守則第一條,女孩子都喜歡童話故事。java
那就先來說一個童話故事~程序員
// 有一個公主 // 她生活在一個充滿冒險的奇妙世界裏 // 她碰見了她的白馬王子,帶着她騎着獨角獸環遊世界 // 與龍搏鬥,遇到了會說話的松鼠,以及許多其餘幻想的事情。 function princess () { var adventrures = []; function princeCharming () {}; var unicorn = {}; var dragons = []; var squirrel = "Hello!"; // 但她不得不回到她那充滿家務和大人們的單調世界。 return { // 她常常給身邊的人講她做爲一個公主的奇妙經歷。 story:function () { return adventures[adventures.length - 1]; } } } // 但他們看到的只是一個小女孩在講述關於魔法和幻想的故事 var littleGril = princess(); littleGril.story(); // 即便大人們知道她是真正的公主,他們也不會相信所謂的獨角獸或龍,由於他們永遠看不到它們 // 大人們說它們只存在於小女孩的想象中 // 但咱們知道真正的真理 // 裏面的小女孩真的是個公主
這個故事來自於stackoverflow的一則回答,看不懂不要緊,等閱讀完本文後,回頭再來看這個故事,你會發現你已經徹底瞭解了個人魅力,咳咳@¥%#…………JavaScript
中閉包的魅力。算法
當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包,即便函數是在當前詞法做用域以外執行。 --- 你不知道的JavaScript(上卷)
瀏覽器
來個🌰ruby
function demo() { var a = 1; return function () { return a; } } var a = demo(); console.log(a()); // 1
閉包由兩部分構成:函數,以及建立該函數的環境。閉包
環境由閉包建立時在做用域中的任何局部變量組成。函數
閉包實際上是JavaScript
函數做用域的反作用產品。
閉包是一種特殊的對象。
所謂有意栽花花不開,無意插柳柳成蔭
,不是JavaScript
故意要使用閉包,而是因爲JavaScript
的函數內部可使用函數外部的變量,這段代碼又剛恰好符合閉包的定義。
在JavaScript
中,外部函數調用以後其變量對象本應該被銷燬,但閉包阻止了它們的銷燬,咱們仍然能夠訪問外部函數的變量對象。
進一步的說,一般狀況下,函數的做用域及其全部變量都會在函數執行結束後被銷燬。可是,若是建立了一個閉包的話,這個函數的做用域就會一直保存到閉包不存在爲止。
function addCalculator (x) { return function (y) { return x + y; } } var add1 = addCalculator(1); console.log(add1(1)); //2 // 釋放對閉包的引用 add1 = null; console.log(add1(1)); //Uncaught TypeError: add1 is not a function
咱們能夠用閉包來作什麼呢?
瞭解Java
的同窗可能知道,Java
是支持私有方法的,私有方法只能被一個類中的其餘方法所調用,可是JavaScript
沒有提供這種原生支持,因此咱們能夠經過閉包來模擬私有方法。
私有方法天然有私有方法的好處,私有方法有利於限制對代碼的訪問,並且能夠避免非核心的方法干擾代碼的公共接口,減小全局污染。
來個🌰
var calculator = (function(){ var a = 1; function addCalculator(val){ a += val } return { add1:function() { addCalculator(1); }, add2:function() { addCalculator(2); }, result:function() { return a } } })(); console.log(calculator.result()); // 1 calculator.add1(); console.log(calculator.result()); // 2 calculator.add2(); console.log(calculator.result()); // 4
上面這種方式也叫作模塊模式(module pattern)。
由於閉包可使函數中的變量都保存在內存中,形成很大的內存消耗,因此若是 不是某些特定的任務須要使用閉包,咱們不要濫用它。
不少博客中都提到了這一點,可是其實都是不徹底對的。
敲黑板!!!
使用不當的閉包會在IE(IE9)
以前形成內存泄漏問題。由於它的JavaScript
引擎使用的垃圾回收算法是引用計數法,對於循環引用將會致使GC
(下文會介紹)沒法回收垃圾。
關於各個瀏覽器的閉包測試,詳情請見司徒正美-js閉包測試
都9102年了,全國開始實行垃圾分類了,你竟然還不知道垃圾回收機制,趕快來補習一下!
垃圾回收也就是GC(Garbage Collection)
。
GC
把程序不用的內存空間視爲垃圾,找到它們而且將它們回收,讓程序員能夠再次利用這部分空間。
不是全部的語言都有GC
,通常存在於高級語言中,如Java
、JavaScript
、Python
。那麼在沒有GC
的世界裏,程序員就比較辛苦,只能手動去管理內存,好比在C
語言中咱們能夠經過malloc/free
,在C++
中的new/delete
來進行管理。
由於這一部分的內容不少,本文只進行簡單的講解,若是想深刻了解垃圾回收算法的同窗能夠在文末獲取學習資料。
世界上首個值得記念的GC
算法是GC標記-清除算法
。由於自其問世以來,一直到半個世紀後的今天,它依然是各類處理程序所用的偉大的算法。
GC標記-清除算法
由標記階段和清除階段構成,標記階段將全部的活動對象作上相應的標記,清除階段把那些沒有標記的對象,也就是非活動對象進行回收。在搜索對象並進行標記的時候使用了深度優先搜索,儘量的從深度上搜索樹形結構。
優勢:
1.算法簡單,實現容易。2.與保守式的GC算法兼容。
缺點:
1.在使用過程當中會出現碎片化的狀況,如同Windows
的文件系統同樣,致使
無數的小分塊散佈在堆的各個地方。2.分配速度,因爲分塊的不連續性,算法每次分配的時候都須要遍歷空閒鏈表爲了找到足夠大的分塊,這樣最糟糕的狀況就是遍歷到最後才找到合適的分
塊,影響了分配速度。
這種方法中引入了計數器的概念,經過計數器來表示對象的「人氣指數」,也就是有多少個程序引用了這個對象。當計數器(引用數)爲0時,垃圾馬上被回收。
優勢:
1.能夠當即回收垃圾。2.最大暫停的時間短。
3.而且沒有必要沿指針查找。
缺點:
1.上文提到過的循環引用沒法回收。2.而且實現起來很複雜。
3.計數器值的增減處理十分繁重。
4.同時計數器須要佔不少位,致使內存空間的使用效率大大下降。
軟件工程沒有銀彈,這些缺點也都有相應的辦法進行解決,若是你想深刻了解垃圾回收算法,能夠購買垃圾回收的算法與實現這本書去看,建議支持正版。
歡迎關注個人我的公衆號,文章將同步發送,後臺回覆【福利】便可免費領取海量學習資料。
你的前端食堂,記得按時吃飯。
ps:你也能夠後臺回覆垃圾回收便可領取相關資料一份~