目次
チェーン コール
部分アプリケーション
一部のアプリケーションの問題
カリー化
ああ、カレーです。機能は何ですか?
関数の組み合わせ
関数結合の結合法則
ホームページ ウェブフロントエンド jsチュートリアル JavaScriptでの関数の組み合わせとカリー化を詳しく解説(例付き)

JavaScriptでの関数の組み合わせとカリー化を詳しく解説(例付き)

Oct 13, 2018 pm 02:42 PM
javascript node.js 関数型プログラミング

この記事では、JavaScript 関数の組み合わせとカリー化について詳しく説明します (例を示します)。必要な方は参考にしていただければ幸いです。

私たちは皆、オブジェクト指向 SOLID における単一責任原則 (SRP、単一責任原則) を知っています。関数型プログラミングでは、各関数は 1 つの単位であり、実行することは 1 つだけです。しかし、現実の世界は常に複雑であり、現実の世界をプログラミングにマッピングする場合、単一の関数ではあまり意味がありません。このとき、関数の合成とカリー化が必要になります。

チェーン コール

jQuery を使用したことがある場合は、$('.post').eq(1).attr('data などのチェーン コールが何であるかをご存知でしょう。 - test', 'test').JavaScript のネイティブ文字列および配列メソッドの一部は、チェーン呼び出しスタイルを記述することもできます:

'Hello, world!'.split('').reverse().join('') // "!dlrow ,olleH"
ログイン後にコピー

まず第一に、チェーン呼び出しは上記のオブジェクトに基づいています。メソッド splitreversejoin は、前のオブジェクト「Hello, world!」から分離されている場合は再生できません。

関数型プログラミングでは、メソッドはデータから独立しています。関数型の方法で上記を書くことができます。

const split = (tag, xs) => xs.split(tag)
const reverse = xs => xs.reverse()
const join = (tag, xs) => xs.join(tag)

join('',reverse(split('','Hello, world!'))) // "!dlrow ,olleH"
ログイン後にコピー

あなたは間違いなく、冗談だと言うでしょう。これは連鎖呼び出しよりもどのように優れているのでしょうか?これは依然としてデータに依存しています。「Hello, world!」を渡さないと、一連の関数の組み合わせは機能しません。ここでの唯一の利点は、個々のメソッドを再利用できることです。パニックにならないでください。後でコンテンツがたくさんあるので、私が最適化します (愚かにも​​)。変換を進める前に、まず部分適用とカリー化という 2 つの概念を紹介します。

部分アプリケーション

部分アプリケーションは、いくつかのパラメータを受け取り、受け取ったパラメータの少ない関数を返すプロセスです。これはアプリケーションの一部です。 bind を使用して実装します。

const addThreeArg = (x, y, z) => x + y + z;

const addTwoArg = addThreeNumber.bind(null, 1)
const addOneArg = addThreeNumber.bind(null, 1, 2)

addTwoArg(2, 3) // 6
addOneArg(7) // 10
ログイン後にコピー

上記は bind を使用して、残りのパラメーターをそれぞれ受け入れる他の 2 つの関数を生成します。これはアプリケーションの一部です。もちろん、他の方法でも行うことができます。

一部のアプリケーションの問題

一部のアプリケーションの主な問題は、返される関数の型を直接推論できないことです。前述したように、一部のアプリケーションは、返されるパラメーターの数を指定せずに、より少ないパラメーターを受け入れる関数を返します。これは暗黙的なものなので、コードを確認する必要があります。そうして初めて、返された関数が受け取るパラメーターの数がわかります。

カリー化

カリー化の定義: 関数を呼び出すことはできますが、すべてのパラメーターを一度に渡すことはできません。この関数は、次の 1 つの パラメータを受け取る関数を返します。

const add = x => y => x + y
const plusOne = add(1)
plusOne(10) // 11
ログイン後にコピー

カリー化された関数は、パラメーターを 1 つだけ受け取る関数を返し、返される関数の型は予測可能です。

もちろん、実際の開発では、多くの関数はカリー化されていません。いくつかのツール関数を使用して変換できます。

const curry = (fn) => { // fn可以是任何参数的函数
  const arity = fn.length;

  return function $curry(...args) {
    if (args.length < arity) {
      return $curry.bind(null, ...args);
    }

    return fn.call(null, ...args);
  };
};
ログイン後にコピー

オープン ソース ライブラリ Ramda で提供されているカリー メソッドを使用することもできます。

ああ、カレーです。機能は何ですか?

const currySplit = curry((tag, xs) => xs.split(tag))
const split = (tag, xs) => xs.split(tag)

// 我现在需要一个函数去split ","

const splitComma = currySplit(',') //by curry

const splitComma = string => split(',', string)
ログイン後にコピー

カリー関数が新しい関数を生成するとき、それはデータとは何の関係もないことがわかります。新しい関数を生成する 2 つのプロセスを比較すると、カリー化を行わないプロセスは比較的冗長です。

関数の組み合わせ

最初にコードを指定します:

const compose = (...fns) => (...args) => fns.reduceRight((res, fn) => [fn.call(null, ...res)], args)[0];
ログイン後にコピー

実際、compose は合計 2 つのことを行います:

  1. Receives関数のセット、関数を返します。関数はすぐには実行されません。

  2. 結合関数。渡された関数を左から右に結合します。

一部の学生は上記のreduceRightにあまり慣れていないかもしれません。2元と3元の例を挙げましょう:

const compose = (f, g) => (...args) => f(g(...args))
const compose3 = (f, g, z) => (...args) => f(g(z(...args)))
ログイン後にコピー

関数呼び出しは左から順に行われます。右、データ 左から右への流れも同様です。もちろん、右から左へを定義することはできますが、意味的にはそれほど意味がありません。

さて、最初の例を最適化しましょう:

const split = curry((tag, xs) => xs.split(tag))
const reverse = xs => xs.reverse()
const join = curry((tag, xs) => xs.join(tag))

const reverseWords = compose(join(''), reverse, split(''))

reverseWords('Hello,world!');
ログイン後にコピー

これははるかにシンプルで理解しやすいでしょうか?ここの reverseWords は、前に説明した Pointfree コード スタイルでもあります。データや外部状態に依存せず、組み合わせた関数です。

Pointfree 前回の記事で JS 関数型プログラミングの概念を紹介し、その利点と欠点についても説明しました。興味のある方はぜひご覧ください。

関数結合の結合法則

まず、小学校の知識の足し算の結合法則: a (b c)=(a b) c を確認しましょう。説明はしませんが、理解できるはずです。

振り返ってみると、実際には関数の組み合わせには結合法則があります。

compose(f, compose(g, h)) === compose(compose(f, g), h);
ログイン後にコピー

これは、関数の組み合わせを自由に組み合わせてキャッシュできるという利点です。

const split = curry((tag, xs) => xs.split(tag))
const reverse = xs => xs.reverse()
const join = curry((tag, xs) => xs.join(tag))

const getReverseArray = compose(reverse, split(''))

const reverseWords = compose(join(''), getReverseArray)

reverseWords('Hello,world!');
ログイン後にコピー

補足。心理図: ###########################

以上がJavaScriptでの関数の組み合わせとカリー化を詳しく解説(例付き)の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 簡単な JavaScript チュートリアル: HTTP ステータス コードを取得する方法 Jan 05, 2024 pm 06:08 PM

JavaScript チュートリアル: HTTP ステータス コードを取得する方法、特定のコード例が必要です 序文: Web 開発では、サーバーとのデータ対話が頻繁に発生します。サーバーと通信するとき、多くの場合、返された HTTP ステータス コードを取得して操作が成功したかどうかを判断し、さまざまなステータス コードに基づいて対応する処理を実行する必要があります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法を説明し、いくつかの実用的なコード例を示します。 XMLHttpRequestの使用

関数プログラミングに C++ ラムダ式を使用する利点は何ですか? 関数プログラミングに C++ ラムダ式を使用する利点は何ですか? Apr 17, 2024 am 10:18 AM

C++ ラムダ式は、関数型プログラミングに次のような利点をもたらします。 シンプルさ: 匿名インライン関数により、コードの可読性が向上します。コードの再利用: コードの再利用を容易にするために、ラムダ式を渡したり保存したりできます。カプセル化: 別の関数を作成せずにコードの一部をカプセル化する方法を提供します。実際のケース: リスト内の奇数をフィルタリングします。リスト内の要素の合計を計算します。ラムダ式は、関数型プログラミングの簡素化、再利用性、カプセル化を実現します。

遅延評価を使用して Golang 関数型プログラムを最適化するにはどうすればよいですか? 遅延評価を使用して Golang 関数型プログラムを最適化するにはどうすればよいですか? Apr 16, 2024 am 09:33 AM

Go では、遅延データ構造を使用して遅延評価を実装できます。実際の値をカプセル化し、必要な場合にのみ評価するラッパー型を作成します。関数型プログラムでのフィボナッチ数列の計算を最適化し、実際に必要になるまで中間値の計算を延期します。これにより、不要なオーバーヘッドが排除され、関数型プログラムのパフォーマンスが向上します。

Golang 関数型プログラミングのよくある間違いと落とし穴 Golang 関数型プログラミングのよくある間違いと落とし穴 Apr 30, 2024 pm 12:36 PM

Go で関数型プログラミングを使用する場合に注意すべき 5 つの一般的な間違いと落とし穴があります。 参照を誤って変更することを避け、新しく作成された変数が返されるようにしてください。同時実行の問題を解決するには、同期メカニズムを使用するか、外部の可変状態のキャプチャを避けます。コードの可読性と保守性を向上させるために、部分的な機能化は控えめに使用してください。アプリケーションの堅牢性を確保するために、常に関数内のエラーを処理してください。パフォーマンスへの影響を考慮し、インライン関数、フラット化されたデータ構造、操作のバッチ処理を使用してコードを最適化します。

JSのAI時代が到来! JSのAI時代が到来! Apr 08, 2024 am 09:10 AM

JS-Torch の概要 JS-Torch は、構文が PyTorch に非常に似ている深層学習 JavaScript ライブラリです。これには、完全に機能するテンソル オブジェクト (追跡された勾配で使用可能)、深層学習レイヤーと関数、および自動微分エンジンが含まれています。 JS-Torch は JavaScript での深層学習の研究に適しており、深層学習の開発を加速するための便利なツールや機能を多数提供します。 Image PyTorch は、Meta の研究チームによって開発および保守されているオープンソースの深層学習フレームワークです。ニューラル ネットワーク モデルを構築およびトレーニングするための豊富なツールとライブラリのセットを提供します。 PyTorch は、シンプル、柔軟、そして使いやすいように設計されており、その動的な計算グラフ機能により、

Python ラムダ式: 匿名関数の威力を明らかにする Python ラムダ式: 匿名関数の威力を明らかにする Feb 24, 2024 am 09:01 AM

Python のラムダ式は、匿名関数の別の構文形式です。これは、プログラム内のどこにでも定義できる小さな匿名関数です。ラムダ式はパラメータ リストと式で構成されます。式には有効な Python 式を使用できます。ラムダ式の構文は次のとおりです: lambdaargument_list:expression. たとえば、次のラムダ式は 2 つの数値の合計を返します: lambdax,y:x+y. このラムダ式は、マップなどの他の関数に渡すことができます。 () 関数:数値=[ 1,2,3,4,5]結果=マップ(ラムダ

Python ラムダ式: 省略、簡潔、強力 Python ラムダ式: 省略、簡潔、強力 Feb 19, 2024 pm 08:10 PM

pythonLambda 式は、簡潔で読みやすく、使いやすいコードを作成するための強力で柔軟なツールです。これらは、他の関数に引数として渡したり、変数に保存したりできる匿名関数をすばやく作成するのに最適です。 Lambda 式の基本構文は次のとおりです。 lambdaarguments:expression たとえば、次の Lambda 式は 2 つの数値を加算します: lambdax,y:x+y この Lambda 式は、次のように引数として別の関数に渡すことができます。 defsum( x ,y):returnx+yresult=sum(lambdax,y:x+y,1,2) この例では

バックエンド開発における Golang と Node.js の比較 バックエンド開発における Golang と Node.js の比較 Jun 03, 2024 pm 02:31 PM

Go と Node.js には、型指定 (強い/弱い)、同時実行性 (ゴルーチン/イベント ループ)、ガベージ コレクション (自動/手動) の違いがあります。 Go は高スループットと低レイテンシーを備えており、高負荷のバックエンドに適しています。Node.js は非同期 I/O に優れており、高い同時実行性と短いリクエストに適しています。この 2 つの実際のケースには、Kubernetes (Go)、データベース接続 (Node.js)、Web アプリケーション (Go/Node.js) が含まれます。最終的な選択は、アプリケーションのニーズ、チームのスキル、個人の好みによって異なります。

See all articles