一篇文章搞懂閉包。

直接進入主題,閉包是什麼?

  • 閉包是寫代碼過程產生的一種天然結果,而不是一種概念。
  • 相比於一些概念性的解釋,更重要的是熟悉它的應用場景、及常見寫法。
  • 若是非要用一句話定義閉包:
    我更加認同《你不知道的javaScript》做者的一句話:當函數能夠記住並訪問所在的詞法做用域時,就產生了閉包。

因此本文將會從閉包的應用場景入手,來印證kyle simpson的這句話。java

列舉兩個常見應用場景

  1. 場景一:封裝函數的私有屬性和方法閉包

    //local變量是foo函數的私有屬性,只能經過bar函數來訪問。
    function foo() {
      const local = 1
      function bar() {
        return local
      }
      return bar
    }
    let bar = foo()
    console.log(bar()) // 1

    bar函數記住了foo函數的詞法做用域,致使foo函數運行完後並不會被垃圾回收,咱們能夠經過bar函數盡情地訪問foo函數的做用域。函數

  2. 場景二:給10個li添加點擊事件code

    // 錯誤寫法:
    function bindEvent() {
      var li = document.querySelectorAll('li')
      for(var i = 0; i < 10; i++) {
        li[i].addEventListener('click', function bar(){
          console.log(i)
        })
      }
    }
    bindEvent() //不管點擊哪一個li,都會打印出10

    錯誤的緣由很明顯,10個bar函數中的i訪問的都是同一個i,這個i屬於foo函數。事件

    // 正確寫法:
    function bindEvent() {
      var li = document.querySelectorAll('li')
      for(var i = 0; i < 10; i++) {
        li[i].addEventListener('click', (function foo(j){
          return bar() {
            console.log(j)
          }
        }))(i)
      }
    }
    bindEvent()

    bar函數記住了foo函數的詞法做用域,foo函數爲每一個bar函數選好了屬於它本身的i,等着bar去訪問就好啦。ip

總結:

閉包的應用場景還有不少,能夠說是隨處可見了。
理解它的核心思想:函數能夠記住並訪問所在的詞法做用域,才能夠根據你本身的意願來識別、擁抱和影響閉包的思惟環境。作用域

相關文章
相關標籤/搜索