跳至內容
Astera Technology

每次建立函式,都可以有自己的狀態

輪流呼叫兩個計數器,分清每次改的是哪個值。

下載完整個案資料及參考答案 ↓

先追這段程式

同一個 counter 工廠建立 a、b,再按例子的次序呼叫。兩者各自記住多少?

完整原始程式
function counter(){let value=0;return ()=>++value;}
const a=counter(),b=counter();
console.log(JSON.stringify([a(),a(),b(),a(),b()]));
確實的 console 輸出
[1,2,1,3,2]
值與執行位置
呼叫次序結果呼叫後的狀態
a(), a()1, 2a=2; b=0
b(), a(), b()1, 3, 2a=3; b=2

結果為何如此

每次 counter() 都建立新的 value。傳回的函式仍可讀寫當次環境,因此 a、b 各自累加。這份狀態隨函式保留,不會自動存到磁碟,也不是權限隔離。

比較另一種寫法

value 放到工廠外面,兩個計數器便共用同一數字。以下另開例子,不會沿用上面的狀態。

另開的有限例子
let value=0;function counter(){return ()=>++value;}
const a=counter(),b=counter();
console.log(JSON.stringify([a(),a(),b(),a(),b()]));
另一寫法的輸出
[1,2,3,4,5]

試清邊界

原例五次呼叫後,再執行 a()、b() 和新建的 counter()(),各得多少?

查看參考答案

依次是 4、3、1。新建的環境由零開始,與舊計數器無關。

重新建立的邊界例子
function counter(){let value=0;return ()=>++value;}
const a=counter(),b=counter();[a(),a(),b(),a(),b()];
console.log(JSON.stringify([a(),b(),counter()()]));
邊界例子的輸出
[4,3,1]

原始例子檔案