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

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

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

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

Q&A

2回答

1142閲覧

ES6 コンストラクタの引数とコールバック関数

or3

総合スコア13

ECMAScript

ECMAScriptとは、JavaScript類の標準を定めるために作られたスクリプト言語です。

JavaScript

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

0グッド

3クリップ

投稿2019/07/23 03:07

Webプログラミングを学習する目的で、読めそうなnpmパッケージ(ideas)を読んでいたところ、挙動が分からない箇所があったので質問させてください。

以下のようにインスタンスを作成する処理がありました。((省略)部分は私が編集したものです)

javascript:

1var idea = new Idea(err => { 2 if (err) { return logger.log(err, "error"); } 3 var commands = { 4 create: callback => { 5 ....(省略).... 6 } 7 ....(省略).... 8 , help: () => { 9 ....(省略).... 10 } 11 }; 12 13 if (~process.argv.indexOf("-h") || ~process.argv.indexOf("--help")) { 14 return commands.help(); 15 } 16 17 if (!commands[process.argv[2]]) { 18 process.argv[2] = "filter"; 19 } 20 21 commands[process.argv[2]]((err, res) => { 22 ....(省略).... 23 display(res); 24 }); 25});

クラス定義はこのようになっています。

javascript

1class Idea { 2 constructor (path, callback) { 3 if (typeof path === "function") { 4 callback = path; 5 path = null; 6 } 7 8 // Defaults 9 this.path = path = path || DEFAULT_PATH; 10 callback = callback || (err => { if (err) throw err }); 11 12 // Init 13 if (!isThere(this.path)) { 14 this.ideas = []; 15 this.save(callback); 16 } else { 17 this.list((err, ideas) => { 18 if (err) { return callback(err); } 19 this.ideas = ideas; 20 callback(null, ideas, this); 21 }); 22 } 23 } 24 /** 25 * list 26 * Lists all ideas. 27 * 28 * @name list 29 * @function 30 * @param {Function} callback The callback function. 31 * @return {Idea} The `Idea` instance. 32 */ 33 list (callback) { 34 rJson(this.path, (err, content) => { 35 if (err) { return callback(err); } 36 callback(err, content); 37 }); 38 return this; 39 } 40 ....(省略)... 41 create (idea, callback) { 42 ....(省略).... 43 } 44 ....(省略)... 45} 46 47module.export = Idea;

コンストラクタによれば、このクラスは第一引数にパス名、第二引数にコールバック関数を受け取るようになっていますが、宣言時には無名関数でerr=>{}だけを渡しています。

質問1

コンストラクタで無理やり各引数の値をnullにしたりcallback=pathにしたりしているのは、JavaScriptではコンストラクタを複数作って引数の型や数で使い分けるような機能がないからでしょうか?また、こうした書き方はJS文化的に一般的なのでしょうか

質問2

listメソッドはコールバック関数を受け取り、Ideaインスタンスを返すとありますが、そのコールバック関数はthis.list()において

javascript

1this.list((err, ideas) => { 2 if (err) { return callback(err); } 3 this.ideas = ideas; 4 callback(null, ideas, this); 5});

と実装されており、この挙動がわかりません。この3つの引数をとるコールバック関数は一体どこでどんな役割を果たしているのでしょうか?

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

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

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

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

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

guest

回答2

0

多重定義

コンストラクタで無理やり各引数の値をnullにしたりcallback=pathにしたりしているのは、JavaScriptではコンストラクタを複数作って引数の型や数で使い分けるような機能がないからでしょうか?

私の知る範囲では、現在のJavaScript(ECMAScript)に多重定義はありません。

文化≠私が好ましいと思う書き方

こうした書き方はJS文化的に一般的なのでしょうか

「文化」で一括りにするものではないと思いますが、私は好ましくない書き方だと思います。
引数の数によって、第一引数のタイプが変わるのは複雑なだけなので、必須引数を前に持ってきて、第二引数以降をオプションにする方が分かりやすいと私は思います。

JavaScript

1new Idea(callback, path);

ECMAScript のビルトイン関数にも同様の思想があり、リファレンスでは下記のように表現される事があります。ます。

JavaScript

1Idea(callback [, path])

前述の多重定義では、下記のようになり、

JavaScript

1Idea(callback) 2Idea(path, callback)

解説的にも学習コスト的にも効率が悪いと感じます。

callback(null, ideas, this)

JavaScript

1this.list((err, ideas) => { 2 if (err) { return callback(err); } 3 this.ideas = ideas; 4 callback(null, ideas, this); 5});

callback で検索すれば、constructor の第二引数にある事が分かります。
公式サイトを読めば、Promise.prototype.catch() に近い動きをしている事が分かります。

JavaScript

1// Dependencies 2var Idea = require("idea"); 3 4// Initialize the idea object 5var idea = new Idea("./ideas.json", err => { 6 if (err) throw err; 7 idea.create("Implement something cool.", err => { 8 if (err) throw err; 9 }); 10});

ただし、Promise.prototype.then() の役割も持っているようで、err === null の場合は、then() の動きをします。
その為、第一引数の truthy 判定で分岐させているわけですが、融合させるメリットがちょっと分かりません。
第三引数でとれるはずのインスタンスを変数 idea で参照しているのも美しくないですね。
全体として、洗練されたコードではない印象を受けました。

Re: or3 さん

投稿2019/07/24 13:03

編集2019/07/25 09:43
think49

総合スコア18156

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

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

or3

2019/07/25 13:07 編集

ご回答ありがとうございます。 > 多重定義 よくよくドキュメントなりを読めばそのように書いてありました。引数の数があってないけどとくにエラーは出さない挙動などびっくりしましたが、柔軟なのですね。 > JS文化 なにぶん学習して日が浅く、コードを読むにしても自由度の高さゆえなのか歴史的な慣習なのか属人的な手癖なのか、パターンが見えてこないものが多くて不安になってました。"文化" という言葉はちょっと悪かったですね。ともあれ、身近に聞ける人がいない中、「洗練されたコードではない」との印象を語っていただけたのは幸いです。自分がついていけないのかと落ち込むところでした 2019/07/25 21:59 追記箇所を拝見しました。 > 学習コストが高い こうした指摘は初学者には思いもつかない、実態に即した意見に思われ、非常に貴重なポイントだと感じました。「読めそう〜」と軽い気持ちで適当に挑んでしまって長考しました.... 人のコードを読む経験がほとんど無いのでよい経験になった、と思うことにします。もっと読めそうなところから読んで書いて馴染んでいきたいと思います
guest

0

分かる範囲で。

コンストラクタで無理やり各引数の値をnullにしたりcallback=pathにしたりしているのは、JavaScriptではコンストラクタを複数作って引数の型や数で使い分けるような機能がないからでしょうか?

そうだと思います。

また、こうした書き方はJS文化的に一般的なのでしょうか

JS文化とおっしゃってますが、全員が全員必ずしも同じ文化に染まっているとは限らないです(全世界規模が大きいと思われますし)。
私だったら、nullを取りうる値は後ろに持ってくると思います。

この3つの引数をとるコールバック関数は一体どこでどんな役割を果たしているのでしょうか?

コンストラクタに渡したcallback関数に(null, ideas, this)の3つの引数を渡しているだけでは。
(つまりコールバックを渡す側が、この引数を受け取ってどうするか決めること)

このパッケージが何をするものか知らないので、JSとして読める範囲でお答えしました。

追記:
コンストラクタ云々は、もし引数の値を直接書いた場合に、

JavaScript

1new Idea("なんかのパス", function(err, ideas, event) { 2 (何らかの処理) 3});

って書くほうが、仮に必ず第1引数がコールバック関数を書くものなら

JavaScript

1new Idea(function(err, ideas, event) { 2 (何らかの処理) 3}, "なんかのパス");

ってなって見づらいからかもしれないです。憶測ですが。

投稿2019/07/24 12:30

編集2019/07/24 12:39
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

退会済みユーザー

退会済みユーザー

2019/07/24 12:40

一応念の為、追記に書いたコールバックの引数は適当です。あしからず。
or3

2019/07/25 04:21

ご回答ありがとうございます。 "文化"について、@think49さんへのコメントにも付記しましたが、言葉選びが悪かったと思います。参考にできるような綺麗なコードと何がしたいのかよくわからんし古の記法も混じってる謎コードの違いを判別できない初学者ゆえ、とりあえず読めそうなのを模倣しようというつもりで読んでいたのですが、この意識はダメですね。「三島由紀夫みたいな文体の人もいれば町田康みたいな文体の人もいる」程度の気持ちで臨もうかと思います。 `callback`はコンストラクタの第二引数で受け取っており、このクラスの中で共通な関数に見えつつ、場所によって引数を1~3個取る書き方をしていて非常に分かりづらいのが、今回の自分の分からなさの原因に思われました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

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

ただいまの回答率
85.51%

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

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

質問する

関連した質問