JavaScript における複数の矢印関数はどういう意味ですか? 質問する

JavaScript における複数の矢印関数はどういう意味ですか? 質問する

私はたくさんの反応するコードを見ると、理解できない次のような箇所があります:

handleChange = field => e => {
  e.preventDefault();
  /// Do something here
}

ベストアンサー1

あれはカリー化された関数

まず、2 つのパラメータを持つこの関数を調べます。

const add = (x, y) => x + y
add(2, 3) //=> 5

カレー風味でまた登場です…

const add = x => y => x + y

以下は矢印関数なしの同じコード1です。

const add = function (x) {
  return function (y) {
    return x + y
  }
}

焦点を当てるreturn

別の方法で視覚化すると役立つかもしれません。矢印関数がこのように動作することはわかっています。戻り値に特に注目してみましょう。

const f = someParam => returnValue

つまり、関数は関数addを返します。わかりやすくするために括弧を使うことができます。太字のテキストは関数の戻り値です。add

const add = x => (y => x + y)

言い換えればadd、ある数値は関数を返す

add(2) // returns (y => 2 + y)

カリー化された関数の呼び出し

したがって、カリー化された関数を使用するには、少し異なる方法で呼び出す必要があります...

add(2)(3)  // returns 5

これは、最初の (外側の) 関数呼び出しが 2 番目の (内側の) 関数を返すためです。2 番目の関数を呼び出して初めて、実際に結果が返されます。呼び出しを 2 行に分けると、このことがより明確になります。

const add2 = add(2) // returns function(y) { return 2 + y }
add2(3)             // returns 5

新しい理解をコードに適用する

関連している:「バインディング、部分適用、カリー化の違いは何ですか?」

さて、仕組みがわかったので、コードを見てみましょう

handleChange = field => e => {
  e.preventDefault()
  /// Do something here
}

まず、矢印関数を使わずに表現してみましょう...

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  };
};

ただし、矢印関数は構文的にバインドされるためthis実際には次のようになります...

handleChange = function(field) {
  return function(e) {
    e.preventDefault()
    // Do something here
    // return ...
  }.bind(this)
}.bind(this)

これで、これが何をしているのかがより明確にわかるかもしれません。 関数handleChangeは、指定された の関数を作成していますfield。これは、アプリケーションの状態を更新するために各入力に独自のリスナーを設定する必要があるため、React の便利なテクニックです。 関数を使用することでhandleChange、各フィールドにリスナーを設定することにつながる重複コードをすべて排除できますchange。すばらしい!

1thisここでは、元のadd関数がコンテキストを使用しないため、レキシカルバインドを行う必要はありませんでした。したがって、この場合、コンテキストを保持することは重要ではありません。


さらに多くの矢

必要に応じて、2つ以上の矢印関数を連続させることができます。

const three = a => b => c =>
  a + b + c

const four = a => b => c => d =>
  a + b + c + d

three (1) (2) (3) // 6

four (1) (2) (3) (4) // 10

カリー化された関数は驚くべきことができる。以下では、$2つのパラメータを持つカリー化された関数として定義されているが、呼び出し側では任意の数の引数を与えることができるように見える。カリー化とは、アリティ-

const $ = x => k =>
  $ (k (x))
  
const add = x => y =>
  x + y

const mult = x => y =>
  x * y
  
$ (1)           // 1
  (add (2))     // + 2 = 3
  (mult (6))    // * 6 = 18
  (console.log) // 18
  
$ (7)            // 7
  (add (1))      // + 1 = 8
  (mult (8))     // * 8 = 64
  (mult (2))     // * 2 = 128
  (mult (2))     // * 2 = 256
  (console.log)  // 256

部分適用

部分適用は関連する概念です。部分適用はカリー化と同様に関数を部分的に適用することを可能にしますが、関数はカリー化された形式で定義される必要はありません。

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)

const add3 = (x, y, z) =>
  x + y + z

partial (add3) (1, 2, 3)   // 6

partial (add3, 1) (2, 3)   // 6

partial (add3, 1, 2) (3)   // 6

partial (add3, 1, 2, 3) () // 6

partial (add3, 1, 1, 1, 1) (1, 1, 1, 1, 1) // 3

partialブラウザで試せるデモはこちらです-

const partial = (f, ...a) => (...b) =>
  f (...a, ...b)
  
const preventDefault = (f, event) =>
  ( event .preventDefault ()
  , f (event)
  )
  
const logKeypress = event =>
  console .log (event.which)
  
document
  .querySelector ('input[name=foo]')
  .addEventListener ('keydown', partial (preventDefault, logKeypress))
<input name="foo" placeholder="type here to see ascii codes" size="50">

おすすめ記事