ポイントフリースタイル
引数に名前を付けずに関数を合成します。
「ポイントフリースタイル」はCoddyKit上の無料JavaScript Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはJavaScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 JavaScript Academyコースには全4レッスンが含まれています。
ポイントフリースタイルとは
ポイントフリー(またはタキトスタイル)とは、引数に触れずに他の関数を組み合わせて関数を定義するスタイルです。引数は暗黙的に渡される対象となります。
function double(n) { return n * 2; }
const nums = [1, 2, 3];
// pointed: argument named explicitly
console.log(nums.map((n) => double(n))); // [2, 4, 6]
// point-free: no named argument
console.log(nums.map(double)); // [2, 4, 6]関数を直接渡す
コールバックが引数を別の関数にそのまま渡すだけなら、ラッパーで包む代わりに、その関数を名前で直接渡せます。
const len = (s) => s.length;
const words = ["a", "bb", "ccc"];
console.log(words.map((w) => w.length)); // pointed: [1, 2, 3]
console.log(words.map(len)); // point-free: [1, 2, 3]関数合成
ポイントフリーのコードでは合成を多用します。ある関数の出力を次の関数に渡して、新しい関数を構築する方法です。
const compose = (f, g) => (x) => f(g(x));
const inc = (n) => n + 1;
const double = (n) => n * 2;
const incThenDouble = compose(double, inc);
console.log(incThenDouble(3)); // (3+1)*2 = 8pipeヘルパー
pipeは左から右へ処理するため、多くの人にとってcomposeよりもわかりやすく感じられます。関数を順番に適用します。
const pipe = (...fns) => (x) => fns.reduce((acc, f) => f(acc), x);
const inc = (n) => n + 1;
const double = (n) => n * 2;
const f = pipe(inc, double);
console.log(f(3)); // 8パイプラインを構築する
pipeを使うと、データに名前を付けることなく、複数段階の変換を名前付き関数として表現できます。
const pipe = (...fns) => (x) => fns.reduce((a, f) => f(a), x);
const trim = (s) => s.trim();
const lower = (s) => s.toLowerCase();
const clean = pipe(trim, lower);
console.log(clean(" HELLO ")); // "hello"カリー化でポイントフリーにする
カリー化によって、複数の引数を取る関数を、1つの引数を取る関数の連鎖に変換できます。これにより、合成にそのまま使える単項関数が得られます。
const multiply = (a) => (b) => a * b;
const triple = multiply(3);
console.log([1, 2, 3].map(triple)); // [3, 6, 9]部分適用
一部の引数をあらかじめ固定すると、直接渡せる特化した関数が得られます。これもポイントフリーのコードを書く方法の1つです。
const add = (a, b) => a + b;
const add10 = add.bind(null, 10);
console.log([1, 2, 3].map(add10)); // [11, 12, 13]述語を合成する
複数の関数からブール値を返すヘルパーを構築すると、インラインの矢印関数を減らした、すっきりしたポイントフリーのフィルターを作成できます。
const isEven = (n) => n % 2 === 0;
const negate = (fn) => (x) => !fn(x);
const isOdd = negate(isEven);
console.log([1, 2, 3, 4].filter(isOdd)); // [1, 3]読みやすさとのトレードオフ
ポイントフリーは elegant に書けますが、やりすぎると難解になります。意図が明確になる場合(map(double))に使い、引数に名前を付けたほうが理解しやすい場合は、ポイントフリーにしないでください。
const names = ["ada", "bob"];
console.log(names.map((n) => n.toUpperCase())); // ["ADA","BOB"]メソッド参照の落とし穴
メソッドを名前で渡すと、thisが失われることがあります。関数がオブジェクトのコンテキストに依存している場合は、ラッパーで包むかbindしてください。
const calc = {
factor: 2,
scale(n) { return n * this.factor; }
};
console.log([1, 2].map(calc.scale.bind(calc))); // [2, 4]実際の変換を合成する
小さな名前付き関数を組み合わせてパイプラインにすると、宣言的でテストしやすいポイントフリーのデータフローを構築できます。
const pipe = (...fns) => (x) => fns.reduce((a, f) => f(a), x);
const toNums = (arr) => arr.map(Number);
const onlyPos = (arr) => arr.filter((n) => n > 0);
const sum = (arr) => arr.reduce((a, n) => a + n, 0);
const process = pipe(toNums, onlyPos, sum);
console.log(process(["3", "-1", "4"])); // 7確認問題
ポイントフリースタイル
まとめ
ポイントフリースタイルでは、引数に名前を付けず、他の関数を合成して関数を構築します。関数参照を渡し(map(double))、compose/pipeで合成し、カリー化または部分適用で単項関数を作成します。メソッド参照でthisが失われる点に注意し、引数に名前を付けたほうが読みやすい場合は、無理にポイントフリーにしないでください。
よくある質問
「ポイントフリースタイル」レッスンは無料ですか?
はい。「ポイントフリースタイル」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、JavaScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 JavaScript Academyコースには全4レッスンが含まれています。
「ポイントフリースタイル」で何を学びますか?
引数に名前を付けずに関数を合成します。 ブラウザで直接実行するハンズオンコードでJavaScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。
JavaScript Academyを始めるのに経験は必要ですか?
事前経験は必要ありません。CoddyKitのJavaScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。
「ポイントフリースタイル」レッスンにはどのくらい時間がかかりますか?
ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。
このJavaScript Academyレッスンでコードを書いて実行できますか?
はい。すべてのJavaScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。
このコースのすべてのレッスン
- 純粋関数と副作用
- 宣言的なデータ変換
- ミューテーションを避ける
- ポイントフリースタイル