JavaScript - 認識閉包


Posted by Andy Tsai on 2020-05-10

什麼是閉包?

閉包是即使函式在其範疇之外被調用,也仍能記得並存取其範疇的能力。

聽起來有點抽象,沒關係,我們來看Code

function foo(){
  var a = 2;
  function bar(){
    console.log(a)
  }
  return bar
}

var baz = foo() 
baz() // 2

一般來說,函式執行完後,Javascript引擎的垃圾回收的機制會釋放不再使用的記憶體,

回到上面的code,照垃圾回收機制,foo()執行之後,它整個內層就應該消失了,
那為何後面調用bar時,依然能順利存取到foo()中的變數a呢?

這是因為bar()仍保留一個參考指向foo()內的範疇(那個參考就叫閉包),
而JS看到這種情形,會為你保留變數a,讓它不被釋放,
所以我們後面即使在範疇之外調用,才能順利取到變數a。

我們可以簡單定義一下閉包:閉包就是一個函式能取到另一個已結束函式的變數,直到取用的函式也結束為止。

閉包其實常出現在我們的程式中

其實我們的程式中或多或少都有閉包的存在,只是我們還沒學會閉包時,認不出它是閉包

像是這段看起來隨處可見的callback

function wait(message){
  setTimeout(function timer() {
    console.log(`say ${message}`)
  }, 1000)
}
wait('hi');

事實上,如果不是閉包,wait內層早就被釋放了,
是timer()仍然有個參考指向message,wait中的變數才能夠被保存起來,不被釋放,也讓我們的程式能順利運作

只要我們常把函式當成一級函式到處傳遞,就很有可能時常發現閉包的出現。

單獨的IIFE算是閉包嗎?

var a = 2;
(function IIFE(){ 
    console.log(a)
}())

廣義來說算,但嚴格來說不算,
因為a是經由正常的範疇查找動作找到的,並不是透過閉包。

廣義的閉包?
廣義來說所有的函式都是閉包,在JavaScript中只要有函式被建立,閉包就會自然地產生。想了解更多可以看Huli大大的文章
所有的函式都是閉包:談 JS 中的作用域與 Closure

模組

有一些編程模式也運用了閉包的概念,像是模組,
模組模式可以讓我們隱藏私有資訊,並選擇對外公開的API

function CoolModule() {
  var count = 0; 
  var message = 'hello';

  function increment() {
    count += 1
    console.log(count)
  }

  function saySomething() {
    console.log(message);
  }

  return {
    increment: increment,
    saySomething: saySomething,
  };
}


var foo = CoolModule()

foo.increment() // 1
foo.saySomething() // 'hello'

這段code中count和message就是我們的私有資訊,而return的物件回傳值則是我們公開的API

也可以達到資料隔離的效果

var foo = CoolModule()
var foo2 = CoolModule()
foo.increment() // 1
foo.increment() // 2

foo2.increment() // 1

行使模組模式的兩個必要條件

  • 必須有一個外層函式,且它必須至少被調用一次
  • 外層函式必須至少回傳一個內層函式,以形成閉包,因此得以存取/修改私有變數

Reference:
You Don't Know JS: Scope & Closures


#javascript #closure #w3HexSchool







Related Posts

This is shell script for example code

This is shell script for example code

我要成為前端工程師的學習筆記:HTML & CSS 篇 - CSS Reset、display Day5

我要成為前端工程師的學習筆記:HTML & CSS 篇 - CSS Reset、display Day5

[02] Functional Component

[02] Functional Component


Comments