JS 中的閉包是什麼?

本文爲飢人谷講師方方原創文章,首發於 前端學習指南html

大名鼎鼎的閉包!面試必問。
請用本身的話簡述前端

  1. 什麼是「閉包」。
  2. 「閉包」的做用是什麼。

首先來簡述什麼是閉包

假設上面三行代碼在一個當即執行函數中(爲簡明起見,我就不寫當即執行函數了,影響讀者理解)。面試

評論裏沒看完就說我寫得有問題的,請看清楚哦:編程

上面三行代碼在一個當即執行函數中。ruby

三行代碼中,有一個局部變量 local,有一個函數 foo,foo 裏面能夠訪問到 local 變量。微信

好了這就是一個閉包:閉包

「函數」和「函數內部能訪問到的變量」(也叫環境)的總和,就是一個閉包。編程語言

就這麼簡單。函數

有的同窗就疑惑了,閉包這麼簡單麼?學習

「我據說閉包是須要函數套函數,而後 return 一個函數的呀!」

好比這樣:

function foo(){
  var local = 1
  function bar(){
    local++
    return local
  }
  return bar
}

var func = foo()
func()

這裏面確實有閉包,local 變量和 bar 函數就組成了一個閉包(Closure)。

爲何要函數套函數呢?

是由於須要局部變量,因此才把 local 放在一個函數裏,若是不把 local 放在一個函數裏,local 就是一個全局變量了,達不到使用閉包的目的——隱藏變量(等會會講)。

這也是爲何我上面要說「運行在一個當即執行函數中」。

有些人看到「閉包」這個名字,就必定以爲要用什麼包起來才行。其實這是翻譯問題,閉包的原文是 Closure,跟「包」沒有任何關係。

因此函數套函數只是爲了造出一個局部變量,跟閉包無關。

爲何要 return bar 呢?

由於若是不 return,你就沒法使用這個閉包。把 return bar 改爲 window.bar = bar 也是同樣的,只要讓外面能夠訪問到這個 bar 函數就好了。

因此 return bar 只是爲了 bar 能被使用,也跟閉包無關。

閉包的做用

閉包經常用來「間接訪問一個變量」。換句話說,「隱藏一個變量」。

假設咱們在作一個遊戲,在寫其中關於「還剩幾條命」的代碼。
若是不用閉包,你能夠直接用一個全局變量:

window.lives = 30 // 還有三十條命

這樣看起來很不妥。萬一不當心把這個值改爲 -1 了怎麼辦。因此咱們不能讓別人「直接訪問」這個變量。怎麼辦呢?

用局部變量。

可是用局部變量別人又訪問不到,怎麼辦呢?

暴露一個訪問器(函數),讓別人能夠「間接訪問」。

代碼以下:

!function(){

  var lives = 50

  window.獎勵一條命 = function(){
    lives += 1
  }

  window.死一條命 = function(){
    lives -= 1
  }

}()

簡明起見,我用了中文 :)

那麼在其餘的 JS 文件,就可使用 window.獎勵一條命() 來漲命,使用 window.死一條命() 來讓角色掉一條命。

看到閉包在哪了嗎?

閉包究竟是什麼?

五年前,我也被這個問題困擾,因而去搜了 stackoverflow 並總結下來。你在百度搜閉包,那篇《JavaScript閉包——懂不懂由你,反正我是懂了》就是我寫的。當時我仍是新手,一直不理解爲何你們口中的閉包這麼模糊、這麼琢磨不定呢。
咱們從新來審視一下閉包的代碼:

第一句是變量聲明,第二句是函數聲明,第三句是 console.log。
每一句我都學過,爲何合起來我就看不出來是閉包?

我告訴你答案,你根本不須要知道閉包這個概念,同樣可使用閉包!

閉包是 JS 函數做用域的副產品。

換句話說,正是因爲 JS 的函數內部可使用函數外部的變量,因此這段代碼正好符合了閉包的定義。而不是 JS 故意要使用閉包。

不少編程語言也支持閉包,另外有一些語言則不支持閉包。

只要你懂了 JS 的做用域,你天然而然就懂了閉包,即便你不知道那就是閉包!

所謂閉包的做用

若是咱們在寫代碼時,根本就不知道閉包,只是按照本身的意圖寫,最後,發現知足了閉包的定義。

那麼請問,這算是閉包的做用嗎?

這個問題,留給你思考。

關於閉包的謠言

閉包會形成內存泄露?

錯。

說這話的人根本不知道什麼是內存泄露。內存泄露是指你用不到(訪問不到)的變量,依然佔居着內存空間,不能被再次利用起來。

閉包裏面的變量明明就是咱們須要的變量(lives),憑什麼說是內存泄露?

這個謠言是如何來的?

由於 IE。IE 有 bug,IE 在咱們使用完閉包以後,依然回收不了閉包裏面引用的變量。

這是 IE 的問題,不是閉包的問題。參見司徒正美的這篇文章

一個小經驗

編程界崇尚以簡潔優雅惟美,不少時候

若是你以爲一個概念很複雜,那麼極可能是你理解錯了。

完。

加微信號: astak10或者長按識別下方二維碼進入前端技術交流羣 ,暗號:寫代碼啦

每日一題,每週資源推薦,精彩博客推薦,工做、筆試、面試經驗交流解答,免費直播課,羣友輕分享... ,數不盡的福利免費送

相關文章
相關標籤/搜索