js函數式編程(二)-柯里化

這節開始講的例子都使用簡單的TS來寫,儘可能作到和es6差異不大,正文以下

咱們在編程中必然須要用到一些變量存儲數據,供從此其餘地方調用。而函數式編程有一個要領就是最好不要依賴外部變量(固然容許經過參數傳遞咯),如何解決這個矛盾的問題呢?將函數柯里化`Curry`就能夠了,這種技巧可讓函數記住一些歷史數據,也就是緩存,怎麼作呢? 說柯里化以前必須先說一下閉包,由於這是實現柯里化的方法。 javascript

閉包

const fun = () => {
  let a = 0;
  return () => {
    a += 1;
    return a;
  };
};
const fa = fun();
console.log(fa()); // 1
console.log(fa()); // 2
console.log(fa()); // 3

每次運行這個函數竟然結果不同,why?由於`a`是`fun`函數內部變量,而這個變量又被`fun`返回的函數依賴,`fun()`執行後,fa所指向的那個函數(`fun`的返回值)還在依賴着`a`。根據js的垃圾回收機制,只要`fa`存在,那麼`a`就不會被釋放,一直在內存中。 進一步想,既然`a`做爲局部變量被依賴着就一直存在,那麼這個局部變量要是參數是否是也有一樣的效果呢,答案是確定的。 java

const fun = (a: number) => {
  return () => {
    a += 1;
    return a;
  };
};
const fa = fun(1);
console.log(fa()); // 2
console.log(fa()); // 3
console.log(fa()); // 4

好,閉包就講這麼多。回到柯里化。 es6

柯里化

柯里化由函數閉包實現。咱們把上面的例子改一改 編程

const fun = (a: number) => (b: number) => {
  return a + b
};
const add2 = fun(2);
console.log(add2(2)); // 4
console.log(add2(3)); // 5
console.log(add2(4)); // 6

`fun(2)`就是`(b) => b+2`,因此`add2(2)`天然是`4`。以上就是柯里化,參數能夠前後傳入,所有傳完才計算。以上是es6或ts的代碼實現,比較簡陋。事實上你徹底沒必要要本身去實現一個函數的柯里化。可使用成熟的庫如ramda。ramda庫還包含了不少已經柯里化的函數。 緩存

import { curry } from 'ramda'
const fun = curry((a: number, b: number) => {
  return a + b
});
const add2 = fun(2);
console.log(add2(2)); // 4
console.log(add2(3)); // 5
console.log(add2(4)); // 6

把一個你要柯里化的函數,原封不動的給curry函數,返回的就是柯里化的函數。但要注意函數參數從左往右的順序是依次傳給柯里化後函數的順序。have fun! 閉包

相關文章
相關標籤/搜索