[進階 js 08] Closure


Posted by tzutzu858 on 2021-03-25

Closure (閉包)是什麼?

closure 是在一個 function 裡面 return function

function test(){
  var a = 10
  function inner() {
    a++
    console.log(a)
  }
  return inner
}
var func = test()

func() // inner() // 答案是 11
func() // 答案是 12
func() // 答案是 13

那為什麼要叫 Closure (閉包) ?
是因為 inner 這個 function 可以把 a 的值記起來,鎖在自己 function 的感覺
不然照理說當 function 結束以後,它的資源都會被釋放
所以在外部 function func 也可以改變 inner function 裡面的值


Closure (閉包)的實際應用

例如假設有一個很複雜的計算

function complex(num) {
  // 複雜計算
  return num * num * num
}

console.log(cacheComplex(20)) 
console.log(cacheComplex(20)) 
console.log(cacheComplex(20)) 
console.log(cacheComplex(20))

每 call 一次都要做一次複雜計算
但輸入一樣,輸出應該也要一樣
所以可以寫一個 function 叫做 cache
然後預想 const cacheComplex = cache(complex)
第一次的 console.log(cacheComplex(20)) 是計算
但第二次的 console.log(cacheComplex(20)) 直接輸出結果
那 cache 這個 function 要怎麼完成呢 ? 如以下範例

function complex(num) {
    // 假裝是複雜計算
    console.log('calculate')
    return num * num * num
}

function cache(func){
    var ans = {}
    return function(num) {
        if (ans[num]) {
            return ans[num]
        }

        ans[num] = func(num)
        return ans[num]
    }
}

console.log(complex(20)) // 計算
console.log(complex(20)) // 計算


const cacheComplex = cache(complex)
console.log(cacheComplex(20)) // 計算
console.log(cacheComplex(20)) // 不用再次計算,直接輸出結果
console.log(cacheComplex(20)) // 不用再次計算,直接輸出結果

出來會是...

calculate
8000
calculate
8000
calculate
8000
8000
8000

解釋 cache(complex)
complex 是一個 function
那他把 complex 這個 function 傳進去 cache 這個 function

然後 cache 這個 function 裡面 return 一個新的 function

function cache(func){
    var ans = {}
    return function(num) {
        if (ans[num]) {
            return ans[num]
        }

        ans[num] = func(num)
        return ans[num]
    }
}

而 cacheComplex 其實就是 return 的這個 function

第一次執行 cacheComplex(20) 因為 ans 裡面沒有值
所以是執行

ans[num] = func(num)
return ans[num]

可以把它看成

ans[num] = cache(complex(20))
return ans[num]

結果是 8000
第二次執行 cacheComplex(20) 因為 ans 裡面已經有值了
所以執行

if (ans[num]) {
    return ans[num]
}

沒有經過計算,直接 return 8000
如果覺得不好懂
也可以把 cache 這個 function 改寫一下

function cache(func){
    var ans = {}
    return function(num) {
        if (ans[num]) {
            return ans[num]
        }

        ans[num] = func(num)
        return ans[num]
    }
}

寫成

function cache(func){
    var ans = {}
    function inner(num) {
        if (ans[num]) {
            return ans[num]
        }

        ans[num] = func(num)
        return ans[num]
    }
    return inner
}









Related Posts

Nuxt(3) - store & 生命週期

Nuxt(3) - store & 生命週期

在html檔中呈現編輯器JS standard style空格

在html檔中呈現編輯器JS standard style空格

AWS Solutions Architect - Associate (SAA) 學習計畫與備考心得: Module 7

AWS Solutions Architect - Associate (SAA) 學習計畫與備考心得: Module 7


Comments