JS核心知識點梳理——上下文、做用域、閉包、this(中)

clipboard.png

引言

滿滿的乾貨,面試必bei系列,參考大量資料,並集合本身的理解以及相關的面試題,對JS核心知識點中的做用域、閉包、this、上下文進行了梳理。上一篇介紹了做用域和上下文。由於感受這兩個概念互相糾纏,上下文的生成會依賴做用域規則。本篇重點介紹閉包和this。程序員

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,指的是當前函數的執行主體;誰讓函數執行的,那麼this就指向誰app

  • 在全局做用域下,this指向window;
  • 函數體中的this,看函數執行前有沒有".",若是有,那麼點前面是誰,this就指向誰;若是沒有「.」,那麼會指向window;
  • 若是給元素的事件行爲綁定方法,那麼方法中的this,就會指向當前被綁定的那個元素;
  • 回調函數中的this指向window;
  • 自執行函數中的this永遠指向window;
  • call 、apply、bind能夠改變this關鍵字;
  • 構造函數中的this指向當前類的實例;

clipboard.png

改變this

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的來源,規律,應用。因爲篇幅有限,將在下一篇中會結合各大公司面試題來鞏固這些知識,但願給你們帶來幫助。

相關文章
相關標籤/搜索