每日挑戰,從Javascript面試題目了解一些你可能忽略的概念 – Day11

tags: ItIron2021 Javascript

前言

昨天我們簡單的帶過IIFE,今天的主題則比較刁鑽一些,會用到我們之前談過的許多觀念,也是很多面試者心目中的大魔王,但實際上並沒有這麼複雜! 我們馬上開始吧!

本日題目與解釋

請解釋什麼是閉包(closure)

防雷圖來囉~!

thinking-day11

沒錯,終究是逃不過這一關的! 我們昨天有稍微帶到這個關鍵字,這個觀念關係到js底層是如何運作的,但理解後其實也不是真這麼困難,若要用一句話來說的話,我會給出以下的解釋。

  • 閉包就是函數本身以及他所參照的環境(lexical environment)

也就是不僅是函數本身,函數本身參照外部參數的行為就會製造出閉包,看個常見的例子

function demo() {
  let name = 'Danny'
  return function() {
    console.log(`Hello, my name is ${name}`)
  }
}

const demoFunc = demo()
demoFunc() // Hello, my name is Danny

上述就是閉包的典型範例,很多人會說閉包就是function return function,但實際上只要你的函數有參照到外部的參數就會形成閉包,例如這樣的做法也會產生一個閉包

let b = 5

function add(a) {
  return a + b
}

閉包與一般函數的差別在於,一般函數中的變數在執行後就會從stack memory中消失,但由於閉包會需要不斷的參照外在環境的參數(以上方的例子來說就是b),他需要把那個參照的變數存在更長久保存的heap memory中不斷地引用,直到未來被js本身的垃圾回收機制處理掉。

既然閉包使用這麼麻煩,我們會什麼會需要閉包呢?

很好的問題,就像昨天提過的,遇到這樣的定義問題時,知道它是什麼遠遠不夠,最好是能給出一些為什麼需要它的理由或是一些實際的範例。js其實在很多你平常的使用中就有不斷用到閉包的概念,只是你沒有注意到而已,其中最主要的優勢為

  • 資料封裝(Data encapsulation)

藉由閉包你可以將一些函數或是變數私有化,讓它變得無法被外在的環境影響,藉由在閉包內創造一個私有的state,你可以確保這個變數、函數不會被預期之外的程式碼操作。

當然實際上閉包還有一些眉眉角角,有興趣的朋友別忘了作進一步的搜尋! 很多面試題目也經常會用到閉包的概念,例如一個萬惡的setTimeOut題目

for (var i = 1; i <= 5; i++) {
  setTimeout(()=> {
    console.log(i)
  }, 100)
}

最終的輸出結果是5個6,你也許知道把var改為let就可以輕鬆印出目標的1~5,但…實際上這就是善用閉包的特性才能達到的,同時參照外部環境的行為是基於scope的特性,這你知道嗎?😉

本日核心觀念與總結

核心觀念

閉包(closure)、scope

總結

  • 能簡單說明何謂閉包
  • 了解閉包的主要優點

發表留言