目次
1. はじめに
2. 純粋関数
3. 関数のカリー化
純粋な関数の使用方法とそれらをカリー化する方法を学んだ後、そのような「パッケージ」を書くのは非常に簡単になります。コード:
カリー化と関数の組み合わせの基本的な知識を踏まえて、以下のスタイルでポイントフリーコードを紹介しましょう。
六、声明式与命令式代码
七、尾声

JavaScript 関数プログラミング (1)

Mar 06, 2017 pm 02:14 PM

1. はじめに

関数型プログラミングというと、抽象的で理解できない記号がたくさん詰まった、大学の教授だけが使用しているような、あいまいな学術コードが第一印象になるかもしれません。これらの事。ある時代にはそうであったかもしれませんが、近年ではテクノロジーの発展に伴い、関数型プログラミングが実際の制作において大きな役割を果たしており、クロージャや匿名関数、関数型プログラミングの典型的な特徴 関数型プログラミングは、ある程度、命令型プログラミングを「同化」させています。

過去 2 年間の React の人気に伴い、関数型プログラミングの概念も普及しており、その他のオープンソース ライブラリでも関数型プログラミングの特性が使用されています。 。それでは、関数型プログラミングの知識と概念を紹介しましょう。

2. 純粋関数

中学生の数学の知識をまだ覚えている方にとって、関数 f の概念は、入力 x に対して出力 y = f(x) を生成するというものです。これは最も単純な純粋関数です。 純粋関数の定義は、同じ入力に対して、目に見える副作用や外部環境の状態に依存することなく、常に同じ出力を取得することです。

たとえば、JavaScript では、配列に対する操作には純粋なものとそうでないものがあります。

var arr = [1,2,3,4,5];

// Array.slice是纯函数,因为它没有副作用,对于固定的输入,输出总是固定的
// 可以,这很函数式
xs.slice(0,3);
//=> [1,2,3]
xs.slice(0,3);
//=> [1,2,3]

// Array.splice是不纯的,它有副作用,对于固定的输入,输出不是固定的
// 这不函数式
xs.splice(0,3);
//=> [1,2,3]
xs.splice(0,3);
//=> [4,5]
xs.splice(0,3);
//=> []
ログイン後にコピー

関数型プログラミングでは、必要なのはスライスのような純粋な関数であり、スプライスのような関数ではありません。呼び出されるたびにデータが台無しになります。

なぜ関数型プログラミングは不純な関数を除外するのでしょうか?別の例を見てみましょう:

//不纯的
var min = 18;
var checkage = age => age > min;

//纯的,这很函数式
var checkage = age => age > 18;
ログイン後にコピー


不純なバージョンでは、 checkage この関数の動作は、入力パラメータの age に依存するだけでなく、外部変数 min にも依存します。関数の動作は、外部システム環境によって決定される必要があります。大規模システムの場合、この外部状態への依存が、システムの複雑さを大幅に増大させる主な理由です。

純粋な checkage は関数内のキー番号 18 をハードコーディングしていることがわかりますが、これは拡張性が低く、次の currying でエレガントな関数式を使用してこの問題を解決する方法がわかります。

純粋な関数は、システムの複雑さを効果的に軽減するだけでなく、キャッシュ可能性などの多くの優れた機能も備えています:

import _ from 'lodash';
var sin = _.memorize(x => Math.sin(x));

//第一次计算的时候会稍慢一点
var a = sin(1);

//第二次有了缓存,速度极快
var b = sin(1);
ログイン後にコピー

3. 関数のカリー化

関数のカリー化 (カリー) の定義は非常に簡単です。関数にいくつかの引数を渡し、残りの引数を処理する関数を返すようにします。

たとえば、加算関数 var add = (x, y) => の場合は便利です。

上記の checkage 関数をまだ覚えていますか?次のようにカリー化できます:

//比较容易读懂的ES5写法
var add = function(x){
    return function(y){
        return x + y
    }
}

//ES6写法,也是比较正统的函数式写法
var add = x => (y => x + y);

//试试看
var add2 = add(2);
var add200 = add(200);

add2(2); // =>4
add200(50); // =>250
ログイン後にコピー

実際、カリー化は関数を「プリロード」する方法であり、渡すパラメーターを少なくすることで、これらのパラメーターをすでに記憶している新しい関数を取得します。つまり、これはある意味、パラメータの「キャッシュ」と関数を記述するための非常に効率的な方法:

var checkage = min => (age => age > min);
var checkage18 = checkage(18);
checkage18(20);
// =>true
ログイン後にコピー

4. 関数の組み合わせ

純粋な関数の使用方法とそれらをカリー化する方法を学んだ後、そのような「パッケージ」を書くのは非常に簡単になります。コード:

import { curry } from 'lodash';

//首先柯里化两个纯函数
var match = curry((reg, str) => str.match(reg));
var filter = curry((f, arr) => arr.filter(f));

//判断字符串里有没有空格
var haveSpace = match(/\s+/g);

haveSpace("ffffffff");
//=>null

haveSpace("a b");
//=>[" "]

filter(haveSpace, ["abcdefg", "Hello World"]);
//=>["Hello world"]
ログイン後にコピー

これも関数型コードではありますが、ある意味「エレガントではない」ことに変わりはありません。関数の入れ子の問題を解決するには、「関数合成」を使用する必要があります:

h(g(f(x)));
ログイン後にコピー

私たちが定義する合成は両面テープのようなもので、任意の 2 つの純粋な関数を組み合わせることができます。 3つの機能を兼ね備えた「三面テープ」はもちろん、「四面テープ」や「N面テープ」でも延長可能です。

この柔軟な組み合わせにより、ビルディングブロックのように関数コードを組み合わせることができます:

//两个函数的组合
var compose = function(f, g) {
    return function(x) {
        return f(g(x));
    };
};

//或者
var compose = (f, g) => (x => f(g(x)));

var add1 = x => x + 1;
var mul5 = x => x * 5;

compose(mul5, add1)(2);
// =>15
ログイン後にコピー

5. ポイントフリー

カリー化と関数の組み合わせの基本的な知識を踏まえて、以下のスタイルでポイントフリーコードを紹介しましょう。

注意していただければ、前のコードでは、オブジェクトに付属するメソッドの一部を常に純粋な関数に変換したいことに気づくかもしれません:

var first = arr => arr[0];
var reverse = arr => arr.reverse();

var last = compose(first, reverse);

last([1,2,3,4,5]);
// =>5
ログイン後にコピー


このアプローチには理由があります。

現時点では、Point Free には中国語の翻訳がありません。興味がある場合は、ここで英語の説明を読むことができます:

http://www.php.cn/

中国語の説明は、おそらく「ドン」です。次のような一時的な中間変数に名前を付けます。

var map = (f, arr) => arr.map(f);

var toUpperCase = word => word.toUpperCase();
ログイン後にコピー

この関数では、中間変数として str を使用しますが、この中間変数はコードが少し長くなる以外は意味がありません。このコードを変換しましょう:

//这不Piont free
var f = str => str.toUpperCase().split(' ');
ログイン後にコピー


このスタイルは、不必要な名前を減らし、コードをシンプルで多用途に保つのに役立ちます。もちろん、一部の関数でポイント フリー スタイルを記述するには、コードの他の部分はポイント フリーでない必要があり、ここで独自の選択を行う必要があります。

六、声明式与命令式代码

命令式代码的意思就是,我们通过编写一条又一条指令去让计算机执行一些动作,这其中一般都会涉及到很多繁杂的细节。

而声明式就要优雅很多了,我们通过写表达式的方式来声明我们想干什么,而不是通过一步一步的指示。

//命令式
var CEOs = [];
for(var i = 0; i < companies.length; i++){
    CEOs.push(companies[i].CEO)
}

//声明式
var CEOs = companies.map(c => c.CEO);
ログイン後にコピー


命令式的写法要先实例化一个数组,然后再对 companies 数组进行for循环遍历,手动命名、判断、增加计数器,就好像你开了一辆零件全部暴露在外的汽车一样,虽然很机械朋克风,但这并不是优雅的程序员应该做的。

声明式的写法是一个表达式,如何进行计数器迭代,返回的数组如何收集,这些细节都隐藏了起来。它指明的是做什么,而不是怎么做。除了更加清晰和简洁之外,map 函数还可以进一步独立优化,甚至用解释器内置的速度极快的 map 函数,这么一来我们主要的业务代码就无须改动了。

函数式编程的一个明显的好处就是这种声明式的代码,对于无副作用的纯函数,我们完全可以不考虑函数内部是如何实现的,专注于编写业务代码。优化代码时,目光只需要集中在这些稳定坚固的函数内部即可。

相反,不纯的不函数式的代码会产生副作用或者依赖外部系统环境,使用它们的时候总是要考虑这些不干净的副作用。在复杂的系统中,这对于程序员的心智来说是极大的负担。

七、尾声

任何代码都是要有实际用处才有意义,对于JS来说也是如此。然而现实的编程世界显然不如范例中的函数式世界那么美好,实际应用中的JS是要接触到ajax、DOM操作,NodeJS环境中读写文件、网络操作这些对于外部环境强依赖,有明显副作用的“很脏”的工作。

这对于函数式编程来说也是很大的挑战,所以我们也需要更强大的技术去解决这些“脏问题”。我会在下一篇文章中介绍函数式编程的更加高阶一些的知识,例如Functor、Monad等等概念。

以上就是JavaScript函数式编程(一)的内容,更多相关内容请关注PHP中文网(www.php.cn)!

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、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衣類リムーバー

AI Hentai Generator

AI Hentai Generator

AIヘンタイを無料で生成します。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

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

SublimeText3 中国語版

SublimeText3 中国語版

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

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

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

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 Dec 17, 2023 pm 02:54 PM

WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法 はじめに: 技術の継続的な発展により、音声認識技術は人工知能の分野の重要な部分になりました。 WebSocket と JavaScript をベースとしたオンライン音声認識システムは、低遅延、リアルタイム、クロスプラットフォームという特徴があり、広く使用されるソリューションとなっています。この記事では、WebSocket と JavaScript を使用してオンライン音声認識システムを実装する方法を紹介します。

WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー WebSocket と JavaScript: リアルタイム監視システムを実装するための主要テクノロジー Dec 17, 2023 pm 05:30 PM

WebSocketとJavaScript:リアルタイム監視システムを実現するためのキーテクノロジー はじめに: インターネット技術の急速な発展に伴い、リアルタイム監視システムは様々な分野で広く利用されています。リアルタイム監視を実現するための重要なテクノロジーの 1 つは、WebSocket と JavaScript の組み合わせです。この記事では、リアルタイム監視システムにおける WebSocket と JavaScript のアプリケーションを紹介し、コード例を示し、その実装原理を詳しく説明します。 1.WebSocketテクノロジー

WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 WebSocketとJavaScriptを使ったオンライン予約システムの実装方法 Dec 17, 2023 am 09:39 AM

WebSocket と JavaScript を使用してオンライン予約システムを実装する方法 今日のデジタル時代では、ますます多くの企業やサービスがオンライン予約機能を提供する必要があります。効率的かつリアルタイムのオンライン予約システムを実装することが重要です。この記事では、WebSocket と JavaScript を使用してオンライン予約システムを実装する方法と、具体的なコード例を紹介します。 1. WebSocket とは何ですか? WebSocket は、単一の TCP 接続における全二重方式です。

JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 JavaScript と WebSocket を使用してリアルタイムのオンライン注文システムを実装する方法 Dec 17, 2023 pm 12:09 PM

JavaScript と WebSocket を使用してリアルタイム オンライン注文システムを実装する方法の紹介: インターネットの普及とテクノロジーの進歩に伴い、ますます多くのレストランがオンライン注文サービスを提供し始めています。リアルタイムのオンライン注文システムを実装するには、JavaScript と WebSocket テクノロジを使用できます。 WebSocket は、TCP プロトコルをベースとした全二重通信プロトコルで、クライアントとサーバー間のリアルタイム双方向通信を実現します。リアルタイムオンラインオーダーシステムにおいて、ユーザーが料理を選択して注文するとき

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

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

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 Dec 17, 2023 pm 05:13 PM

JavaScript と WebSocket: 効率的なリアルタイム天気予報システムの構築 はじめに: 今日、天気予報の精度は日常生活と意思決定にとって非常に重要です。テクノロジーの発展に伴い、リアルタイムで気象データを取得することで、より正確で信頼性の高い天気予報を提供できるようになりました。この記事では、JavaScript と WebSocket テクノロジを使用して効率的なリアルタイム天気予報システムを構築する方法を学びます。この記事では、具体的なコード例を通じて実装プロセスを説明します。私たちは

JavaScript で HTTP ステータス コードを簡単に取得する方法 JavaScript で HTTP ステータス コードを簡単に取得する方法 Jan 05, 2024 pm 01:37 PM

JavaScript で HTTP ステータス コードを取得する方法の紹介: フロントエンド開発では、バックエンド インターフェイスとの対話を処理する必要があることが多く、HTTP ステータス コードはその非常に重要な部分です。 HTTP ステータス コードを理解して取得すると、インターフェイスから返されたデータをより適切に処理できるようになります。この記事では、JavaScript を使用して HTTP ステータス コードを取得する方法と、具体的なコード例を紹介します。 1. HTTP ステータス コードとは何ですか? HTTP ステータス コードとは、ブラウザがサーバーへのリクエストを開始したときに、サービスが

JavaScriptでinsertBeforeを使用する方法 JavaScriptでinsertBeforeを使用する方法 Nov 24, 2023 am 11:56 AM

使用法: JavaScript では、insertBefore() メソッドを使用して、DOM ツリーに新しいノードを挿入します。このメソッドには、挿入される新しいノードと参照ノード (つまり、新しいノードが挿入されるノード) の 2 つのパラメータが必要です。

See all articles