Josh Hsu

我以為的閉包不是我以為的閉包...

> 面試官:請解釋一下閉包

我以為的閉包不是我以為的閉包...

前幾天同事問我為什麼這段 code 要這樣寫?

import axios from 'axios' // api.js function getList(params) { return axios.post('/api/getList', params) }
// component import { getList } from '@/api' function getDataList() { // 傳入參數後拿API的資料的function const params = { ... // 包含一堆要送入的參數 } return getList(params) }

問我為什麼要這樣寫之後,跟他解釋後,

他問了這樣的問題:

我以為你是要寫閉包

question

我心想這不是閉包啊,至少跟我認知的閉包定義不一樣,我問他閉包的定義:一個 function 內返回另一個 function 就是閉包不是嗎?因為之前只有看過 MDN 上的定義以及用法而已,於是我開始研究所謂閉包到底是什麼...

// 我認為的閉包 function makeCounter() { let count = 0 return function () { return count++ } } let counter = makeCounter()

#一個 function 內返回另一個 function 就是閉包?

首先我們可以先看 code 是返回 axios 的函式,而 axios 返回的是一個 Promise

// component import { getList } from '@/api' function getDataList() { // 傳入參數後拿API的資料的function const params = { ... // 包含一堆要送入的參數 } return getList(params) }

Promise 物件 代表一個即將完成、或失敗的非同步操作,以及它所產生的值。 from MDN

// 驗證一下 typeof new Promise((resolve) => resolve('Hello')) // 'object'

所以 getDataList 這個 function 返回的是一個 function 嗎?

#怎麼解釋閉包

這兩篇解釋得蠻清楚的

  1. 所有的函式都是閉包

  2. https://zh.javascript.info/closure#la-ji-shou-ji 往上滑一點就能看到 closure

闭包 是指一个函数可以记住其外部变量并可以访问这些变量。在某些编程语言中,这是不可能的,或者应该以一种特殊的方式编写函数来实现。但如上所述,在 JavaScript 中,所有函数都是天生闭包的(只有一个例外,将在 "new Function" 语法 中讲到)。

也就是说:JavaScript 中的函数会自动通过隐藏的 [[Environment]] 属性记住创建它们的位置,所以它们都可以访问外部变量。

在面试时,前端开发者通常会被问到“什么是闭包?”,正确的回答应该是闭包的定义,并解释清楚为什么 JavaScript 中的所有函数都是闭包的,以及可能的关于 [[Environment]] 属性和词法环境原理的技术细节。

#結論

嚴格來說,一個 function 內返回另一個 function 就是閉包,這句話一點也沒錯,因為"所有的函式都是閉包"。但如果面試官問:請解釋一下閉包,這樣的回答是會被打槍並且被洗臉。也是藉由這次的經驗我才完全釐清之前對於閉包的誤解,所以標題才會是"我以為的閉包不是我以為的閉包"。

本篇並沒有打算討論何為閉包或閉包的定義,因為網路上已經有一堆優秀的文章解釋了,主要打這篇文章是為了讓我對於這次學習有個總結,以及附上參考連結讓我以後複習有個參照。

所以你也以為閉包是哪種呢?

  1. 一個 function 內返回另一個 function 就是閉包

  2. 閉包(Closure)是函式以及該函式被宣告時所在的作用域環境(lexical environment)的組合。 - from MDN

  3. 所有的函式都是閉包

#Ref

See all posts