質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Babel

Babelは、JavaScriptの次世代仕様であるECMAScriptのコンパイラ。次世代の標準機能を用いて記述されたコードを、それらの機能に対応していないブラウザでも動作するコードに変換することができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

Q&A

解決済

2回答

1992閲覧

javascriptのreduceの戻り値を関数にしたときの処理の流れがわかりません。

u310ai

総合スコア10

Babel

Babelは、JavaScriptの次世代仕様であるECMAScriptのコンパイラ。次世代の標準機能を用いて記述されたコードを、それらの機能に対応していないブラウザでも動作するコードに変換することができます。

JavaScript

JavaScriptは、プログラミング言語のひとつです。ネットスケープコミュニケーションズで開発されました。 開発当初はLiveScriptと呼ばれていましたが、業務提携していたサン・マイクロシステムズが開発したJavaが脚光を浴びていたことから、JavaScriptと改名されました。 動きのあるWebページを作ることを目的に開発されたもので、主要なWebブラウザのほとんどに搭載されています。

関数

関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

0グッド

2クリップ

投稿2018/07/05 21:06

編集2018/07/05 21:15

javascriptで関数の配列をreduceで回し、reduceの戻り値を関数にして、
その関数の中で処理をしてから戻すといった関数を作ったのですが、処理の流れが思ったと通りではありませんでした。

コードは以下です。

javascript

1const a = () => 'a' 2const b = () => 'b' 3const c = () => 'c' 4const d = () => 'd' 5 6const array = [ a, b, c, d ] 7 8function func(args) { 9 return args.reduce((accum, current, index) => { 10 console.log('=====outer===== index: ' + index + ', accum: ' + accum() + ', current: ' + current()) 11 return (str='*') => { 12 console.log('---inner--- index: ' + index + ', accum: ' + accum() + ', current: ' + current()) 13 return str + accum() + ':' + current() 14 } 15 }) 16} 17 18console.log(func(array)('結果: '))

結果は以下です。

shell

1=====outer===== index: 1, accum: a, current: b 2---inner--- index: 1, accum: a, current: b 3=====outer===== index: 2, accum: *a:b, current: c 4---inner--- index: 1, accum: a, current: b 5---inner--- index: 2, accum: *a:b, current: c 6---inner--- index: 1, accum: a, current: b 7=====outer===== index: 3, accum: **a:b:c, current: d 8---inner--- index: 1, accum: a, current: b 9---inner--- index: 2, accum: *a:b, current: c 10---inner--- index: 1, accum: a, current: b 11---inner--- index: 3, accum: **a:b:c, current: d 12---inner--- index: 1, accum: a, current: b 13---inner--- index: 2, accum: *a:b, current: c 14---inner--- index: 1, accum: a, current: b 15結果: **a:b:c:d

この結果で理解できないのは、
全体的にどのような処理の流れなのかがわかっていないのですが、
特にreduceの戻り値である関数(inner)の処理が何回もされているのと、
func関数の戻り値の関数を呼び出す際に指定した、引数('結果: ')が最後で適用され、それまではundefinedだということです。
こういったコードを説明している日本語のサイトなどがありましたらそちらを載せていただくだけでもありがたいです。

reduxのcomposeの定義を見ている際に理解できないコードがあったので、似ているコードを作って理解しようと思ったらはまってしまいました。

よろしくお願いします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

関数とreduceで実行されることをばらすと、下記のような動作になっています。

JavaScript

1const a = () => 'a' 2const b = () => 'b' 3const c = () => 'c' 4const d = () => 'd' 5 6// 初期値指定がないため最初のaccumは最初の要素になり、indexは1から始まる。 7const accum1 = a; 8const current1 = b; 9const index1 = 1; 10console.log('=====outer===== index: ' + index1 + ', accum: ' + accum1() + ', current: ' + current1()); 11const accum2 = (str='*') => { 12 console.log('---inner--- index: ' + index1 + ', accum: ' + accum1() + ', current: ' + current1()); 13 return str + accum1() + ':' + current1(); 14}; 15const current2 = c; 16const index2 = 2; 17console.log('=====outer===== index: ' + index2 + ', accum: ' + accum2() + ', current: ' + current2()); 18const accum3 = (str='*') => { 19 console.log('---inner--- index: ' + index2 + ', accum: ' + accum2() + ', current: ' + current2()); 20 return str + accum2() + ':' + current2(); 21}; 22const current3 = d; 23const index3 = 3; 24console.log('=====outer===== index: ' + index3 + ', accum: ' + accum3() + ', current: ' + current3()); 25const accum4 = (str='*') => { 26 console.log('---inner--- index: ' + index3 + ', accum: ' + accum3() + ', current: ' + current3()); 27 return str + accum3() + ':' + current3(); 28}; 29console.log(accum4('結果: '));

最初のaccumが単なるaにのはいいとして、問題は次のaccumですが、returnで渡した関数そのものになります。そして、次の処理のouterの所でそのaccumが呼ばれるため、returnで渡した関数の中身が実行されます。上のコードで言うと、accum2がouterで実行されているという所ですね。そのような流れで、どんどんaccumには過去の関数も蓄積され、その度にouterでもよばれているので、何度もinnerが表示されると言うことです。

投稿2018/07/05 22:24

編集2018/07/05 22:25
raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u310ai

2018/07/05 23:50

処理の流れが大変わかりやすく、またどう考えればいいのか勉強になりました! 有難うございました!
guest

0

javascriptで関数の配列をreduceで回し、reduceの戻り値を関数にして、

その関数の中で処理をしてから戻すといった関数を作ったのですが、
(中略)

reduxのcomposeの定義を見ている際に理解できないコードがあったので、似ているコードを作って理解しようと思ったらはまってしまいました。

reduxcompose関数を使ったことがないのですが、冒頭の一文や、composeという言葉から推測するに、やりたいことは質問文に掲載されているようなAではなく、Bではないでしょうか?

// A: 質問文のコードからreducerを取り除いて簡略したもの const func = f => g => v => v + f() + g();

ではなく、

// B: const compose2 = f => g => v => f(g(v)); //とか const compose3 = f => g => h => v => h(f(g(v)));

その上で、Arrayreduceメソッドを使って、複数の関数をcomposeできる便利なユーティリティー関数を作りたいみたいな話が根本的なところにあるのかなと思いました。

これを前提に簡単なデモコードを書いてみました。

// compose関数に渡す関数(curry化は省略) const trim = str => str.trim(); const splitBy = splitter => words => words.split(splitter); const joinWith = jointer => arr => arr.join(jointer); const toLowerCase = str => str.toLowerCase(); const Identity = value => value; const compose = (...funcs) => { return funcs.reduceRight((chainedFunc, currentFunc) => { return (...args) => currentFunc(chainedFunc(...args)) }, Identity) } // 左右の空白除去してハイフン区切りのスラグを作成する関数をcompose const slugify = compose(toLowerCase, joinWith('-'), splitBy(' '), trim) console.log(slugify(' My First Blog Entry ')); // "my-first-blog-entry"

※ 一般的にcomposeというと、引数に渡された関数を右端の関数から順に適用していく場合が多いと思うので、reduceRightを使いました。

投稿2018/07/05 23:47

編集2018/07/06 08:17
HayatoKamono

総合スコア2415

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

u310ai

2018/07/06 00:06

確かに僕が見たサイトのcomposeの説明でもreduceRightを使っていたのですが、 元のコードを見るとreduceを使っておりましたので、これはどういうことかと思い調べていて今回の質問に至りました。 以下が元のコードの該当の部分です。 `return funcs.reduce((a, b) => (...args) => a(b(...args)))` 調べる中でもっとわかりやすくしようと思い、 質問文のようなコードに変えてテストしていました。 これから上記のコードを紐解いていくにあたって、回答していただいたコードは助けになりそうです。 有難うございました!
HayatoKamono

2018/07/06 08:09

どういたしまして!頑張ってください!
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問