iT邦幫忙

2021 iThome 鐵人賽

DAY 21
0
自我挑戰組

邊工作邊進行前端學習之旅系列 第 21

[Day 21] 閉包 (Closure)是什麼?

  • 分享至 

  • xImage
  •  

前言

閉包的觀念,其實就和前幾天談到的作用域、變數宣告和作用域的觀念有關。只要有清楚知道其中差異,在理解閉包上就也能夠透過範例輕鬆理解了~。

學習資源分享

  1. JavaScript - 十分鐘帶你了解 閉包 (Closure),主要是透過六角學院的這個影片來理解,而今天文章範例也是使用該影片中的範例來說明。
  2. 深入淺出瞭解 JavaScript 閉包(closure),PJCHENder的文章,也很清楚的用範例一步步的說明沒有使用閉包會發生什麼情形,閉包的應用方式為何。

範例解說

呼叫函式內的函式

我們主要是要認識作用域,理解變數所能夠被存取的範圍,所以範例中,我們要去注意變數money

  • 在第一層的函式內,宣告變數 money=1000
  • 內層,再撰寫一個function,是執行money - price ,而他能向外取用到 money = 1000的值
  • 在 myMoney 中,會取得 1000,並帶入參數為 price=100 ,執行 1000-100
  • console 出的結果為 900,再去callMethod(),裡面傳入參數 => 會隨參數的數值去扣除
function callMethod() {
  var money = 1000;
  return function (price) {    
    money = money - price;
    return money;
  }
}
let myMoney = callMethod()(100);  // 存取內部函式的變數
console.log(myMoney);

補充說明

為何要宣告變數 let myMoney = callMethod()(100);
若直接呼叫callMethod(),都是回傳函式

所以透過宣告新的變數,將callMethod()中的function存到變數 myMoney 中,並讓該變數可以執行。

增加全域變數 changeMoney

  • 注意changeMoney的宣告,沒有使用var或let,此方式的宣告就會直接為全域變數
    • 如果直接執行changeMoney的話,會使 money 直接為 500
  • 藉此範例,可以看到在閉包中,就是讓宣告的變數存在執行的範圍(函式)內
function callMethod() {
  var money = 1000;
  changeMoney = function () {
    money = 500;
  }
  return function (price) {       // 這裡就是一個閉包,不過目前只會使用一次
    money = money - price;
    return money;
  }
}
let updateMyMoney = callMethod();  // 存取內部函式的變數
console.log(updateMyMoney(100));
  • 在呼叫changeMoney之前,我們隨著帶入參數的數值,會去執行money - price
  • 執行changeMoney()之後,money = 500,帶入參數後,也會從500去扣

閉包的用意

讓一個函式可以存取多個變數,並且能夠分別執行函式中的任務

  • 外層callMethod的函式,帶入newMoney的參數
  • 最後宣告兩個新變數 MyMoney YourMoney,並傳入不同數值

function callMethod(newMoney) {
  var money = newMoney || 1000;
  return function (price) {
    money = money - price;
    return money;
  }
}
let MyMoney = callMethod(500);
let YourMoney = callMethod(1000);
console.log(MyMoney(100));
console.log(YourMoney(100));

記得善用 let,產生區塊作用域

上述有提及因變數在全域環境的關係,所以在呼叫changeMoney時,要取得的值會被覆蓋。
在 ES6 透過 let 它可以幫我們把所定義的變數縮限在 block scoped 中,簡單說就是{}來區隔。

小結

自己的學習習慣,會透過影片課程中老師的解說,而自己邊做筆記、或是跟著範例進行操作,來加深自己的記憶,並透過反覆思索能夠更加理解內容。此外即便看過影片,也做完筆記,有時還會去搜尋 MDN 或是其他部落格文章,看看其他人用什麼角度來說明觀念。


上一篇
[Day 20] JS - 變數宣告
下一篇
[Day 22] JS - 事件委派 Delegation
系列文
邊工作邊進行前端學習之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言