Published on

JavaScriptの関数型プログラミング

Authors
  • avatar
    Name
    Kikusan
    Twitter

Array

const ary = [1, 2, 3, 4, 5]

// 全てに計算を行い返す
console.log(ary.map(e => e * 2)); // Array [2, 4, 6, 8, 10]
// trueのもののみを返す
console.log(ary.filter(e => e % 3 === 0)); // Array [3]
// 一致した最初の要素を返す or undefined
console.log(ary.find(e => e > 3)); // 4
// 一致した最初の要素のインデックスを返す or -1
console.log(ary.findIndex(e => e > 3)); // 3
// 全てに一致するか
console.log(ary.every(e => e !== 0)); // true
// どれか一致するか
console.log(ary.some(e => e < 0)); // false
// 先頭から順に式を適用した結果を積んでいく
console.log(ary.reduce((n, m) => n + m)); // 15
// ソート。前にするなら-1, 後にするなら1を指定
console.log(ary.sort((n, m) => n > m ? -1 : 1)); // Array [5, 4, 3, 2, 1]
// ソートは元オブジェクトもソートされるのでされたくない場合はslice()でシャローコピーする
console.log(ary.slice().sort((n, m) => n > m ? -1 : 1));
// foreach
ary.forEach(e => {console.log(e)}); // 1 2 3 4 5

Object

一度配列に直して使用するのが良い。

const obj = {
    attr1: 1,
    attr2: "str",
    attr3: true,
    func() {}
};

console.log(Object.keys(obj)); // Array ["attr1", "attr2", "attr3", "func"]
console.log(Object.values(obj)); // Array [1, "str", true, func() {}]
console.log(Object.entries(obj)); // Array [Array ["attr1", 1], Array ["attr2", "str"], Array ["attr3", true], Array ["func", func() {}]]

カリー化

部分適用の元の関数を作ること。
部分適用とは、高階関数の引数を段階的に固定していく手法。

// カリー化前
const div = (x, y) => x / y;
//div(1, 3) == 1 / 3, 

// カリー化
// const cdiv = (x) => {
//     return (y) => x / y;
// }
const cdiv = (x) => (y) => x / y;
console.log(cdiv(10)(3));
//=> 10/3 = 3.333...

// 部分適用
var inv = cdiv(1);
console.log(inv(2));
//=> 1/2 = 0.5

クロージャ

関数を関数で包む。
外側の関数にある変数を隠匿できる。

// const counter = () => {
//     let count = 0;
//     const increment = () => {
//         return count += 1;
//     }
//     return increment;
// };
const counter = (count = 0) => () => count += 1;
const increment = counter();
console.log(increment()); // 1
console.log(increment()); // 2

隠匿されたcount変数はincrement変数が廃棄されるまで生き残る。
これはincrementから参照が残っているため。