2018-08-10
Reactでアプリケーションを作っていくときなど、純粋な(副作用のない)関数を最大限使うことが推奨される。
純粋関数(Pure Function)であるためには、基本的に以下の条件を満たしておく必要がある。
3つ目の条件がなかなかのくせもので、意識せずにいると思わぬ副作用を起こしてしまうので注意が必要。特にJavaScriptの場合、配列を操作するときにはもとの配列を直接操作してしまっていないか意識する必要がある。
JavaScriptのArrayオブジェクトに属するメソッドには「破壊的な」メソッドが存在しており、「破壊的な」メソッドはもとの配列を直接操作(破壊)してしまう。一方で「非破壊的な」メソッドとは、配列を直接操作するのではなく、もとの配列のコピーに対して操作を行ってその結果を返す。
破壊的なメソッドと非破壊的なメソッドは混在していて見分けがつかない。これはもう覚えるしかないのでまとめる。
これらのメソッドはもとの配列を直接変化させるので注意しなくてはいけない。
破壊的なメソッドを使わなくても配列の操作は問題なくできる。
スプレッド演算子を使う。破壊的なpush()
やunshift()
は使わない。
const numbers = [1, 2, 3]
const newNumbers = [...numbers, 4]
console.log(newNumbers)
// [1, 2, 3, 4]
filter()
を使う。破壊的なpop()
やshift()
、splice()
は使わない。
const numbers = [ "one", "two", "three"]
const newNumbers = numbers.filter(number => number !== "two")
console.log(newNumbers)
// ["one", "three"]
主に使うのはmap()
とreduce()
の2つ。functionalなJavaScriptを書くためには、この2つをマスターすることが必須。
配列内の各要素を関数fncで順番に加工する。
var numbers = [1, 4, 9, 16];
const newNumbers = numbers.map(x => x * 2);
console.log(newNumbers);
// [2, 8, 18, 32]
配列の各要素を2倍に。
const numbers = [1, 2, 3, 4, 5]
const editNumber = (oldNumber, newNumber, arr) =>
arr.map(number => (number === oldNumber) ? newNumber : number
)
const updatedNumbers = editNumber(3, 100, numbers)
console.log(updatedNumbers)
// [1, 2, 100, 4, 5]
配列内の特定の要素を変更する。条件分岐は三項演算子ですっきり。
initは初期値。隣接する2つの要素を左から右へ関数fncで処理し、単一の値にたたみ込む。
const numbers = [15, 24, 13, 35]
const max = numbers.reduce(
(max, value) => (value > max) ? value : max,
0
)
console.log('max', max);
// max 35
配列から最大値を取り出す。
const numbers = ["one", "one", "two", "three", "two"];
const distinctNumbers = numbers.reduce(
(distinct, number) =>
(distinct.indexOf(number) !== -1) ?
distinct :
[...distinct, number],
[]
)
console.log(distinctNumbers)
// ["one", "two", "three"]
配列から重複した要素を取り除く。
どうしても破壊的なメソッドを使いたいときがある。特にreverse()
やsort()
など。
その場合はもとの配列を変えてしまわないように、スプレッド演算子でコピーを作ってから操作する。
const numbers = [1, 2, 3]
const newNumbers = [...numbers].reverse();
console.log(newNumbers);
// [3, 2, 1]