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

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

ただいまの
回答率

88.77%

コンストラクター、thisに関して分からないことがあります

解決済

回答 2

投稿 編集

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

newyee

score 155

javascriptを勉強している際なのですが、以下のコードに関して分からない部分が出てきてしまったため、教えて頂きたいです。

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">

</head>
<body>
<script>

    var Animal = function() {};

    Animal.prototype = { 
        walk : function() {
            console.log('トコトコ...');
        }
    };

    var Dog = function() {

        Animal.call(this);
    };

    console.log(this);

    Dog.prototype = new Animal();

    Dog.prototype.bark = function(){

        console.log('ワンワン');
    }

    var d = new Dog();
    d.walk();
    d.bark();



</script>
</body>

</html>


教えて頂きたい部分というのは「Animal.call(this);」この部分に関してなのですが、2点お聞きしたいことがございます。
まず、「Animal.call(this);」ここの説明として、「Animalコンストラクターを現在のthisで呼び出しなさい、という意味である。」とあったのですが、現在のthisで呼び出すとは、Animalオブジェクトにプロパティやメソッドが設定されていた場合、グローバルオブジェクトとして呼びだす、といった意味なのでしょうか?
もう一点なのですが、「ここではコンストラクターは空なのでなくても問題はないが、基底クラスでプロパティの定義など、なにかしらの初期化処理を行っている場合には、まず基底クラスのコンストラクターを処理した後、派生クラス独自の初期化処理を記述してください。」との説明があるのですが、クラスを継承する際は、基底クラスのコンストラクターを派生クラス先で処理しなければならない理由は何故なのでしょうか?
多少混乱してしまっている部分があり、うまく説明できていなかったらすみません。
ご解説頂けましたら幸いです。よろしくお願いします。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • m.ts10806

    2018/09/10 11:18

    質問を書ききってしまってからタイトルを考えると良いのではないでしょうか。タイトルを考えてから書くと、標題決めてから作文書くときのように自由に中身が書けないことがあって余計に分かりにくくなることも多々あります。

    キャンセル

  • m.ts10806

    2018/09/10 11:19

    「タグにあるものはタイトルに含まない」「質問内のキーワードを広い集めて組み立てる」といったやり方もあります。

    キャンセル

  • newyee

    2018/09/10 11:32

    ありがとうございます。教えて下さった、「質問内のキーワードをひろい集めて組み立てる」こちらを意識しながら、タイトルを考えていきたいと思います。質問を書ききってしまってからの方がタイトル決めた方が良いですよね。教えて頂いた通り試してみたいと思います!

    キャンセル

回答 2

checkベストアンサー

+2

 Animal.call(this); の意味について

var Dog = function() {
  Animal.call(this);
};


functionの中で実行されていますね。
functionの中というのはthisが指すものが呼び出され方によって変わります。

コードを見るとvar d = new Dog();と、newをつけてインスタンスを生成していますので、こうやって実行されたDogの中では、thisは生成されたDogのインスタンスを指します。
変数dに格納されるものと同一だということです。
で、callは第一引数で指定したオブジェクトを、呼び出した関数内でthisとして扱えという意味になっています。
つまり、var d = new Dog();こうやって実行されたときにはAnimalという関数の中で指すthisも、Dogのインスタンスです。
なので、変数dに格納されたインスタンスの中でのthisはすべてインスタンス自身を指すということになります。

 基底クラスのコンストラクターについて

試しにこんな変更をしてみてください。

var Animal = function(name) {
  this.name = name;
};

// 中略

var Dog = function() {
  // Animal.call(this); 消す
};

// 中略

Dog.prototype.bark = function(){
  console.log('%s「ワンワン」', this.name);
}

Animalが受け取るはずのnameはどこから来るでしょうか?

誰も渡してくれないので、barkメソッドでthis.nameを参照しようとするとundefinedです。
コンソールにはundefined「ワンワン」と出てくると思います。

そこでこう修正してみてください。

var Dog = function(name) {
  Animal.call(this, name);
};

// 中略

var d = new Dog('ジョン');

こう修正すれば、ジョン「ワンワン」と出てくると思います。
Animalのコンストラクタに引数を引き継いで設定したからです。

また、こうやって変更してみたコードを見てみると、Animalのコンストラクタでthis.nameを設定したのに、Dogが持っているメソッドの中でthis.nameを参照できていますね。
これは、ひとつめで説明したようにthisを渡して同じインスタンスを指すようにしてあるからです。

こんな感じで理解できましたか?
もう少し複雑な構成で組み立てていくと、thisを渡したり継承元のコンストラクタを処理したりしなければならない意味がわかってくると思います。

試しに、Animalを継承したCatを作ってみたり、Animalのメソッドをもう少し増やしてみたりいろいろ拡張して遊んでみてください。
んでいろんな場所にログを仕込んでみてください。
聞くよりいろんなことを試してみた方が勉強になると思います。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/09/12 16:02

    ご返信遅れてしまい、すみません。
    ご回答下さった部分で、勉強不足がゆえ理解できず、新しく質問などを立てさせて頂き、調べておりました。
    かなり基礎的な部分が抜けており、まだまだ勉強に励まなければと痛感致しました...
    ご回答頂きましたおかげで、だいぶ「this」に関する理解が出来てきました。
    Catオブジェクトなどを作成し、色々試してみた結果、意外にも予想通りにいったので、やはり色々と試してみなければ分からないと、勉強になりました。
    すみません。何度も申し訳ないのですが、最後に、細かい部分なのですが、ご回答下さったコードの、「console.log('%s「ワンワン」', this.name);」ここの、「%s」とはどういう意味なのでしょうか?
    console出力しましたら、「this.name」の部分が前に来て、ジョン「ワンワン」となっていたので、何か関連があるのかなと思ったもので。調べてみたのですが、いまいちキーワードとヒットしなかったもので、聞かせて頂きました。

    キャンセル

  • キャンセル

  • 2018/09/12 16:19

    %sが変数として機能します。カンマ「,」で区切った後に変数を指定します。
    この例ですとthis.name=”ジョン”が入ります。
    最終的に%s=”ジョン” + "「ワンワン」"となります。

    変数は複数指定可能です。
    console.log('%s%s', "A","B");とすれば、ABと出力されます。

    %sの文字列以外にも%dの数値など色々な書式があります。
    console.logで検索してみてください。

    キャンセル

  • 2018/09/12 16:32

    お二方ともありがとうございました!
    調べてみます!

    キャンセル

0

本題ではありませんが、いまのブラウザではclassとして、継承構造をラッピングすることもできるようになっています(IE11など古いブラウザで動かす場合にはbabelなどで変換が必要です)。

class Animal{
  constructor(name){
    this.name = name;
  }

  walk() {
    console.log('トコトコ...');
  }
}

class Dog extends Animal{
  bark(){
    console.log('ワンワン');
  }
}

この場合、Dogの側にコンストラクタがないように見えますが、同じ引数を親に渡すコンストラクタがあるものとして扱われます。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 88.77%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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