高階函數就是那種輸入參數裏面有一個或者多個函數,輸出也是函數的函數,這個在js裏面主要是利用閉包實現的,最簡單的就是常常看到的在一個函數內部輸出另外一個函數,好比前端
var test = function() { return function() {} }
這個主要是利用閉包來保持着做用域:segmentfault
var add = function() { var num = 0; return function(a) { return num = num + a; } } add()(1); // 1 add()(2); // 2
這裏的兩個add()(1)和add()(2)不會互相影響,能夠理解爲每次運行add函數後返回的都是不一樣的匿名函數,就是每次add運行後return的function其實都是不一樣的,因此運行結果也是不會影響的。數組
若是換一種寫法,好比:緩存
var add = function() { var num = 0; return function(a) { return num = num + a; } } var adder = add(); adder(1); // 1 adder(2); // 3
這樣的話就會在以前運算結果基礎上繼續運算,意思就是這兩個 adder 運行的時候都是調用的同一個 num微信
好比有個函數:閉包
var add = function(a) { return a + 1; }
每次運行add(1)
的時候都會輸出2
,可是輸入1
每次仍是會計算一下1+1
,若是是開銷很大的操做的話就比較消耗性能了,這裏其實能夠對這個計算進行一次緩存。
因此這裏能夠利用高階函數的思想來實現一個簡單的緩存,我能夠在函數內部用一個對象存儲輸入的參數,若是下次再輸入相同的參數,那就比較一下對象的屬性,把值從這個對象裏面取出來。app
const memorize = function(fn) { const cache = {} return function(...args) { const _args = JSON.stringify(args) return cache[_args] || (cache[_args] = fn.apply(fn, args)) } } const add = function(a) { return a + 1 } const adder = memorize(add) adder(1) // 2 cache: { '[1]': 2 } adder(1) // 2 cache: { '[1]': 2 } adder(2) // 3 cache: { '[1]': 2, '[2]': 3 }
用JSON.stringify
把傳給 adder 函數的參數變成了字符串,而且把它當作 cache 的 key,將 add 函數運行的結果當作 value 傳到了 cache 裏面,這樣 memorize 的匿名函數運行的時候會返回cache[_args]
,若是cache[_args]
不存在的話就返回fn.apply(fn,args),把fn.apply(fn, arguments)
賦值給cache[_args]
並返回。
注意:cache不能夠是Map
,由於Map的鍵是使用===
比較的,[1]!==[1]
,所以即便傳入相同的對象或者數組,那麼仍是被存爲不一樣的鍵。函數
const memorize = function(fn) { // X 錯誤示範 const cache = new Map() return function(...args) { return cache.get(args) || cache.set(args, fn.apply(fn, args)).get(args) } } const add = function(a) { return a + 1 } const adder = memorize(add) adder(1) // 2 cache: { [ 1 ] => 2 } adder(1) // 2 cache: { [ 1 ] => 2, [ 1 ] => 2 } adder(2) // 3 cache: { [ 1 ] => 2, [ 1 ] => 2, [ 2 ] => 3 }
本文是系列文章,能夠相互參考印證,共同進步~性能
網上的帖子大多深淺不一,甚至有些先後矛盾,在下的文章都是學習過程當中的總結,若是發現錯誤,歡迎留言指出~學習
參考: <JavaScript模式>P78
PS:歡迎你們關注個人公衆號【前端下午茶】,一塊兒加油吧~
另外能夠加入「前端下午茶交流羣」微信羣,長按識別下面二維碼便可加我好友,備註加羣,我拉你入羣~