滿滿的乾貨,面試必bei系列,參考大量資料,並集合本身的理解以及相關的面試題,對JS核心知識點中的做用域、閉包、this、上下文進行了梳理。上一篇介紹了做用域和上下文。由於感受這兩個概念互相糾纏,上下文的生成會依賴做用域規則。本篇重點介紹閉包和this。程序員
先介紹this,由於我以爲this最簡單了,掌握住分析的方法,依照方法去分析,毫無難度。面試
由於咱們解耦,爲何要解耦?由於咱們要複用!
舉個例子:我費了九牛二虎之力寫了一個方法,能夠對某個數組a進行復雜的操做數組
var a = [xxx,xxx,....] function foo (){ a xxx // do something to a xxx a // do something to a }
這個方法只能a用 耦合性太強。當其餘數組b想用這個方法的時候因爲方法裏面的操做對象固定是a
致使失敗。
固然我也不能寫成b,由於若是數組c要用難道咱們再改爲c?
怎麼辦,顯然這個操做的對象不能是固定的,應該說最好是一個變量,誰調用,這個變量就是誰。
this就這麼產生了!因此說this的可變是業務的須要,咱們要的就是它的可變
。固然你要是掌握不了它的變化規則,那麼對你來講引入this就是一場災難了。閉包
總原則: 函數中的this,指的是當前函數的執行主體;誰讓函數執行的,那麼this就指向誰app
apply call bind能夠改變this函數
問題來了,爲何要改變this?
性能
還記得我以前說的引入this是爲了進行更好的複用嗎?
js裏面沒有類,可是經過原型、繼承js在努力模仿類。同一個類固然能經過繼承複用代碼,不一樣類不繼承的狀況下怎麼複用呢?經過改變this。
舉個例子,Array類有reverse方法。只要是數組,都繼承了Array的reverse方法,能夠直接調用。this
[1,2,3].reverse() //[3,2,1]
如今有個類數組arguments,因爲不屬於Array類,沒有辦法繼承reverse方法,可是我就是想用,咋辦?改變thisspa
Array.prototype.reverse.call(argumengts)
在計算機科學中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函數閉包(function closures),是引用了自由變量的函數
。這個被引用的自由變量將和這個函數一同存在,即便已經離開了創造它的環境也不例外。因此,有另外一種說法認爲閉包是由函數和與其相關的引用環境組合而成的實體
。 wiki
閉包這個東西咋說呢,不一樣的程序員,不一樣的資料都有不一樣的理解。你把它理解爲一個函數,也能夠把它理解爲函數+執行環境。prototype
咱們這裏不糾結閉包的定義。而是關注閉包的現象,應用,再結合相關面試題去攻克它,最後談一下我對閉包的思考。
話說了一籮筐,你卻是給我上代碼呀.....
各位看官息怒,小的再多說幾句
以前咱們說過了,函數執行,生成執行環境。函數執行完,銷燬執行環境。嗯,聽上去很正常,不用的東西就銷燬嘛。
可是若是函數執行完,該函數上下文還用用怎麼辦,有用的東西確定不敢銷燬了。這個就是閉包的現象,那麼能引發這個現象的鄙人就把它理解爲閉包!
function foo () { var a = 1 return function bar () { a++ console.log(a) } } var b = foo() //函數執行完,我就問你foo的上下文你敢銷燬嗎? b() // 2 b() // 3
你們看foo執行完的結果賦值給了b,也就是函數bar賦值給了b,將來我可能讓b執行的,也就是讓bar執行,因此我須要保證bar能訪問上下文不被銷燬。
bar能訪問的上下文其實是foo執行時候的上下文。因此foo執行完之後上下文不會被銷燬,會繼續存在。
個人理解是 函數向外層做用域暴露出了一個內部引用,那麼就存在閉包現象
(真的不必糾結閉包究竟是啥,是函數?內部總體?是xxx?`。
做用1:保存變量
應用: 函數柯里化
var add = (a)=>(b)=> a+b add(2)(3) //5
優勢:延遲執行,提早傳參,逼格高
做用2:保護變量(不受污染)
應用: 單例模式
//jQ源碼 (function(){ var jQuery=function(){ //jq代碼 } window.$=window.jQuery=jQuery; //這個經過window對象暴露給外面,根return的暴露是一個意思 })() //函數執行完了,裏面的引用暴露給外面了,因此上下文不銷燬
優勢:變量和函數都寫到當即執行函數裏面了,避免了污染外層做用域
閉包無處不在,也許你不經意就寫了個閉包。
須要注意的是,因爲閉包會使得函數中的變量都被保存在內存中,內存消耗很大,因此不能濫用閉包,不然會形成網頁的性能問題,在IE中可能致使內存泄露。解決方法是,在退出函數以前,將不使用的局部變量所有刪除。
本篇詳細介紹了閉包和this的來源,規律,應用。因爲篇幅有限,將在下一篇中會結合各大公司面試題來鞏固這些知識,但願給你們帶來幫助。