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

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

ただいまの
回答率

91.77%

  • JavaScript

    9541questions

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

  • jQuery

    4241questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

コンストラクタは返り値は不要?

解決済

回答 3

投稿 2016/01/05 20:36

  • 評価
  • クリップ 0
  • VIEW 577

aaaaaaaa

score 375

「javascript逆引きレシピ」の073pにて、クラス(コンストラクタ)を定義することに関する情報が記載されているのですが、そのクラスを学ぶ際の注意点として、コンストラクタは自動的にthisの指すオブジェクトを返すので返り値はいらないと記述してありました。つまり、インスタンスのもとになる関数は、そのインスタンスを自動的に返すから戻り値はいらないということだと思うのですが、書いてある意味がいまいちわからないのです。
注意を促している箇所で記述されているので、何か大切な理由があると思うのですが、理解できません。
ちなみに、返り値やインスタンスという単語の意味は理解しているつもりですが、このように上記の文章になると何を伝えたかったのか理解できなくなります。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 3

checkベストアンサー

+3

仕様書を確認したところ、かなり複雑な動作をするようです。new F(args)とした場合、最終的にF.[[Construct]](args, F)が呼び出されるのですが、この[[Construct]]は内部メソッド(JavaScriptの内部処理だけに使われるメソッド、コードには現れない)であり、他の関数とは異なる特殊な動作をします。

参考: ECMAScript 2015 9.2.2 Construct

ざくっと動作の概要を説明すると、Fのオブジェクトを作成してそれをthisにbindしたF()を評価した後に、

  1. return文で終わっているとき  
      1-1. returnの結果がObject型であれば、その結果を返す。  
      1-2. そうではなく、Fが基本型(派生型では無い)であれば、作成したFのオブジェクトを返す。  
      1-3. そうではなく、returnの結果がundefinedでなければTypeError例外を発生させる
  2. 1でない、または、1-1〜1-3のどれでもなければ、作成したFのオブジェクトを返す。

という動作をします(厳密ではありませんし、詳しいところまで見てないので間違いがあるかも知れません)。つまり、Fのコンストラクタがreturn {};で終わっていれば、new F(args){}返しますが、Fが基本型でreturn 0;などで終わっていれば、0ではなくFのオブジェクトが返します。そもそもreturn文がない、または、undefinedを返すのであれば、Fのオブジェクトを返します。

なお派生(derived)型以外の全てのクラス(関数)は全て基本(base)型です。派生型はECMAScript 2015のclass構文でextendsを使った場合とジェネレーター以外は無いようです。functionのみを使ったECMAScript 5までの書き方(babel等で変換した場合も同様)であれば、TypeError例外が発生する事は無いので、気にしなくても良いようです。

まとめるとnew演算子でオブジェクトを生成した場合、返ってくる値は下記の通りです。

  1. コンストラクタに値を指定したreturn文がなければ、新たに作成されたそのクラスのオブジェクトが返ります。
  2. コンストラクタに値を指定したreturn文があれば、
        2-1. return文で指定した値がObject型であれば、その指定した値が返ります。
        2-2. それ以外なら、return文がない場合と同じです。
        2-3. ただし、ECMAScript 2015からのclass構文を使っていると例外が発生する場合があります。

法則が複雑で混乱の元なので、値を指定したreturn文は書かない(return文そのものがない、または、return;※のみ)のがいいでしょう。
return;return undefined;と同じですが、その場合も、必ず作成したオブジェクトが返り、例外も発生しません。

投稿 2016/01/05 23:43

編集 2016/01/05 23:54

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

+1

コンストラクター関数が自動的にインスタンスを返すというよりは、関数はthisに対する操作の役割しか持たずに、戻り値は無視されるといったほうがわかりやすいかもしれません。

注意を促したいのは、この 戻り値が無視される という性質についてではないかと思います。
つまり「無視されるので何かをreturnしてもその値が返される訳ではないですよ」という注意なのではないかと。

ちなみにJavaScriptのコンストラクターを理解する上で、個人的にしっくり来た説明を紹介します。

// 普通に初期化
var instance = new SomeClass("初期化パラメーター");

// 以下3行で、ほぼ同じ動きをする
var instance = Object.create(SomeClass.prototype);
var constructor = SomeClass.bind(instance)
constructor("初期化パラメーター");


どこかでこんな説明を見た時、あぁ、そういう動きなんだと納得しました。

5~7行目で、5行目はSomeClassのprototypeオブジェクトをプロトタイプとするオブジェクトを作ります。
new した時も、SomeClassのprototypeオブジェクトをプロトタイプとするオブジェクトができるのでこれは同じです。
6行目、SomeClassをただの関数として実行した時、thisinstanceを指すようにbindされた関数を作成します。
最後にその関数を実行すると、instanceの状態がnewした場合と同じになります。

一番下のconstructor(...)の戻り値は捨てられていますよね。
あくまでinstancethisとした処理をして、instanceの内部状態を初期化する役割しかないということです。

投稿 2016/01/05 21:13

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

0

直感的に考えると、コンストラクタ関数でインスタンスを作ってるんだから、コンストラクタ関数の戻り値としてインスタンスを設定するべきに思える。
しかし直感とは違って、実際はコンストラクタで戻り値を設定する(returnを書く)必要はありません。

ここが直感と違うために、間違いやすいので注意してください。
ってことだと思います。

投稿 2016/01/06 00:42

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    以下のような回答は評価を下げられます

    • 間違っている回答
    • 質問の回答になっていない投稿
    • 不快な投稿

    評価を下げる際はその理由をコメントに書き込んでください。

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

ただいまの回答率

91.77%

関連した質問

同じタグがついた質問を見る

  • JavaScript

    9541questions

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

  • jQuery

    4241questions

    jQueryは、JavaScriptライブラリのひとつです。 簡単な記述で、JavaScriptコードを実行できるように設計されています。 2006年1月に、ジョン・レシグが発表しました。 jQueryは独特の記述法を用いており、機能のほとんどは「$関数」や「jQueryオブジェクト」のメソッドとして定義されています。

閲覧数の多いJavaScriptの質問