iT邦幫忙

2021 iThome 鐵人賽

DAY 23
1
Modern Web

追求JS小姊姊30天系列 第 23

追求JS小姊姊系列 Day23 -- 頭等工具人也看安眠書店? 認識閉包讓你獨佔變數

  • 分享至 

  • xImage
  •  

前情提要

工具人竟敢透露了一些身份的秘密。

:打斷一下,所以為何你們三個工具人出現的瞬間,JS姐妹們就突然消失了?
方函式:喔~終於想起來了嗎?因為一直讓你接觸他們不是很好,所以我使用我的能力:閉包,把他們關起來了。


閉包怎麼做到關人的?

在了解閉包能力之前,你應該要先知道為何會需要閉包?

假設今天我們要計算一個值,但我們把初始值宣告在全域

let balance = 1000;
function caculatePrice(cost){
    balance = balance - cost;
    console.log(balance);
}
//花了100元
caculatePrice(100)
console.log(balance); //900
//再花100元
caculatePrice(100)
console.log(balance); //800

我們可以將它放入函式內,讓它成為區域變數,這樣就不會被大家共用

let balance = 1000;

//開銷計算
function caculateCost(cost){
    balance = balance - cost;
    return balance;
}
//花了100元
caculateCost(100)
console.log(balance,"第一次支出開銷"); //900
//再花100元
caculateCost(100)
console.log(balance,"第二次支出開銷"); //800

//書本開銷計算
function caclateCostOfBook(bookPrice){
    balance = balance - bookPrice;
    return balance;
};
caclateCostOfBook(200);

//然後我們再看一次我們的餘額
console.log(balance,"預期應該為800");

你會發現因為它們共用同一個變數值,所以不論我們執行caclateCostOfBook或是caculateCost時,都會影響balance的值,進而造成計算結果不如預期。

怎麼辦呢?放入函式內


放入函式

因為此時變數讀取有了所謂區域性,這樣就能避免儲存金額的變數,在全域被誤調值。

function caculatePrice(cost){
    let balance = 1000;
    balance = balance - cost;
    console.log(balance);
}
//花了100元
caculatePrice(100)
console.log(balance); //900
//再花100元
caculatePrice(100)
console.log(balance); //800

但另一個問題出現了,不論你執行幾次caculatePrice,都是從最初的金額$1000開始扣除,因為每次呼叫時,balance都會被重新宣告

這時候就是閉包(closure)上場的時刻!


閉包(closure)

先說筆者目前所知閉包最大的功能就是:私有化變數

function caculatePrice(cost){
    let balance = 1000;
    return function (){
     balance = balance - cost;
     console.log(balance);
    }
}
//將匿名函式存入變數
let x = caculatePrice(100);

x();//扣100
x();//再扣100

我們將caculatePrice(100)存入變數x這個動作,實際上你可以視為:將匿名函式存入變數x

x = function (){
     balance = balance - cost;
     console.log(balance);
    }

但不同的是,這個匿名函式保留了對caculatePrice字彙環境的參照,所以能透過 scope chain去讀取內部的值如:balance,cost ,並且在每次執行時去影響數值。


方函式若你把變數想像成姐妹

  1. 當你放在全域:就很像隨時在開放空間的人,隨便想攀談都很正常。
  2. 當你放在函式內:就很像進到一個空間內,只是在那個空間她們不管怎麼活動,都在我的眼皮下,我能隨時關注。
  3. 閉包內:當情況進展太快,你想要斷絕他們關係,就能用閉包

:所以只有這三種區別?

-- to be continued --


那今天就到這邊摟!
每天的休息,是為了後面的追求,明天見。


reference:

你懂 JavaScript 嗎?#15 閉包(Closure)
所有的函式都是閉包:談 JS 中的作用域與 Closure
D10 - 點一籠熱呼呼的小籠閉包 Closure


上一篇
追求JS小姊姊系列 Day22 -- 工具人、姐妹不只身份的差別(中):從識別字開始講起吧
下一篇
追求JS小姊姊系列 Day24 -- 工具人、姐妹不只身份的差別(下):從記憶體看宣告變數的可變性
系列文
追求JS小姊姊30天30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言