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

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

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

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

Q&A

解決済

4回答

366閲覧

javascriptのコールバック関数について

babbleman

総合スコア107

JavaScript

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

0グッド

1クリップ

投稿2020/01/28 04:33

コールバック関数の書き方がイマイチわかっていません。
例えば下記のように書いたとします。

javascript

1function aiueo(){ 2console.log("aiueo"); 3} 4 5function hello(){ 6console.log("hello"); 7}

この時、必ずhelloを実行してからaiueoを実行したいとなった時に、私が調べた文献によると引数に関数を入れるということだったので
コードは下記のようになりますよね。

javascript

1function HelloThenAiueo(callback){ 2hello(); 3callback(); 4}

そして呼び出す際にやっと引数に関数を入れて無事にコールバックが行われます(もしかしたら間違っているかもしれません)

javascript

1HelloThenAiueo(aiueo);

以上のように処理の順番を変えるのに
1、一つ目の関数を定義する
2、二つ目の関数を定義する
3、順番が変わるようにコールバック関数を定義する
4、呼び出す

というように、処理の順番を変えるのに4ステップかかってしまいます。
もっと短く書く方法はあるのでしょうか?
それともこれがコールバック関数という地獄と呼ばれる物なのでしょうか?
もし短くスマートに書く方法がありましたら教えて欲しいです。

個人的には3つ目の二つの関数の順番を確定させるためにわざわざ三つ目の関数を定義する、というステップが一番無駄だと思っています。

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

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

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

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

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

guest

回答4

0

もし短くスマートに書く方法がありましたら教えて欲しいです。

ただ並べて書くだけです。

javascript

1hello(); 2aiueo();

投稿2020/01/28 04:56

maisumakun

総合スコア145183

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

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

maisumakun

2020/01/28 04:57

単に「そのまま動くもの」の順番を変えるのにコールバック関数を使うのは無駄です。
maisumakun

2020/01/28 05:02

「クリックされた時に」動く、「通信データが返ってきた」段階で動く、「配列の各要素」について1つに1回ずつ呼び出す、「条件によっては」呼ぶ必要があるなど、「同期的に1対1で実行する」わけではない場面が、コールバックを必要とする場面です。
guest

0

結論としては以下を覚えて帰りましょう。

  • 関数は引数や戻り値にして色んな所へ持ち運べる
  • 変数や引数などのお尻に()をつければ何でも実行出来る
  • 上2つを利用して、最善のタイミングまで関数の実行を待ってもらって、他人に実行を移譲する事が実現出来る

そこに至るまでに軽く解説していきます

処理の順番を変えるのに4ステップかかってしまいます。

もっと短く書く方法はあるのでしょうか?

ES2015で足されたアロー関数等を利用すればもう少し綺麗に書けますが

しかし、そもそもコールバックは普通の書き方を複雑にするだけなので
「他の手段も考えたけど、どうしてもこれが最善だ!」
というケース以外では使い物になりません。

普通に書けよ間抜けと罵倒されてしまいますね。
まさに同じ感想抱いていませんか?

じゃあどんなケースがコールバック使うのが最善になるの?

JavaScriptというのは基本的にブラウザ上で実行される言語です。
ブラウザはマウスをしゅっと動かすだけでAの要素にホバーされた!Bの要素のホバーが解除された!という風にイベントが大量に飛び交っています。

これのイベントをlistenして、
該当するイベントが呼び出された時に登録しておいた関数を実行するという仕組みになっています。

その最もよくある例がaddEventListenerであり、
elm.addEventListener('click', aiueo)という風に
アプリを作る側のエンジニアはコールバック関数を利用するだけで、
コールバック関数の記述を書く事はめったにありません。
これがコールバック関数の「最善のタイミングまで関数実行を遅らせる」の有効活用が出来た一例でしょう。

我々、Webサイトのエンジニアが書くのは
毎回elm.addEventListener('click', fn)と書くのは面倒やな…せや!

js

1const elm = document.querySelector('.hoge'); 2const click = (elm, cb) => elm.addEventListener('click', cb); 3 4// 楽になったわ 5click(elm, aiueo); 6 7// promise化したいな 8const listen = (elm, type) => new Promise(resolve => { 9 elm.addEventListener(type, resolve); 10}); 11const main = async () => { 12 await listen(elm, 'click'); 13 console.log("クリックされたで"); 14} 15main();

とまぁ、こんな感じで「そもそもコールバック関数を要求する関数を扱う」ラッピング関数を書く程度だと思います。
必要に応じて作れるようになると捗るので覚えて損はないですが、
暫くの間は別に嬉しくもないので別の勉強した方が良いと思います。

投稿2020/01/28 05:14

miyabi-sun

総合スコア21158

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

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

0

ベストアンサー

hello()自体がcallbackを受ければいいんじゃないでしょうか?

javascript

1function hello(callback){ 2 console.log("hello"); 3 if (callback) {callback()}; 4} 5 6hello(); 7hello(function(){console.log("aiueo");}); 8hello(function(){console.log("kakikukeko");});

結果

console

1hello 2hello 3aiueo 4hello 5kakikukeko

投稿2020/01/28 04:55

Y.H.

総合スコア7914

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

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

0

3つ目の二つの関数の順番を確定させるためにわざわざ三つ目の関数を定義する、というステップが一番無駄だと思っています

必要な処理であるなら無駄というものはありません。

callback関数は、何らかの処理結果を引数に受け付けることのできる関数でもあります、単純に順序云々という代物ではありません。

コールバックを実行する関数(HelloThen..)は、必要なら内部実装も膨大にもなりますし、コード上で行数を抑え、見やすくするために外部関数化されることもあります。


もし短くスマートに書く方法

jQuery の登場時に生まれた メソッドチェーン を実現するオブジェクトの定義手法を紹介しておきます。メソッドが thisを返すかぎり、処理を繋ぐことができるのが特徴で、ご質問のように順序を入れ替える必要があるときに使えるかもしれません。

const oj = { callback : null, setCb( cb ) { this.callback = cb; return this; }, hello() { console.log( "hello" ); return this; }, aiueo() { console.log( "aiueo" ); return this; }, fire() { if ("function" === typeof this.callback) { this.callback() } } } // メソッドチェーンでの実行 oj.setCb(()=>console.log("hoge")) .hello() .aiueo() .fire(); oj.aiueo() .setCb(()=>console.log("hogu")) .hello() .fire();

これがコールバック関数という地獄と呼ばれる物なのでしょうか?

違います。受け付けた引数を次々と伝搬しなければならないときに、関数がネストして読みにくくなることをコールバック地獄と言います。

たとえば NodeJS でフレームワークを使わずに、チョットしたサーバー処理を書こうと以下のようなコードを書くとき、app 関数の内部実装です。

javascript

1// NodeJS 2const http=require("http") 3 4const app = function( request, response ) { 5 // any process #1 6 function( request, response ) { 7 // any process #2 8 function( request, response ) { 9 // any process #3 10 function( request, response ) { 11 // any process #4 12 // サーバーからクライアントへのレスポンス処理 13 response.writeHead( err, headers, opt ); 14 response.end( body ); 15 } 16 } 17 } 18} 19 20http.createServer( app ).listen(8080);

投稿2020/01/28 05:59

AkitoshiManabe

総合スコア5432

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問