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

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

ただいまの
回答率

88.61%

ソースの流れに公理はあるのか

解決済

回答 2

投稿 編集

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

aaaaaaaa

score 481

下記のソースは、初歩的なモーダルウィンドウが記述されたものです。
ソースの流れとして

function Modal(el) {
    this.initialize(el);
}

Modal.prototype.initialize = function(el) {//initialize…初期化する
    this.$el = el;
    this.$container = $("#modal");
    this.$contents = $("#modal-contents");
    this.$close = $("#modal-close");
    this.$next = $("#modal-next");
    this.$prev = $("#modal-prev");
    this.$overlay = $("#modal-overlay");
    this.$parents = this.$el.parents("ul");
    this.$window = $(window);
    this.handleEvents();
};

Modal.prototype.handleEvents = function() {

    var self = this;

    this.$parents.on("click","a", function(e) {
        self.show(e);
        return false;
    });

    this.$close.on("click",function(e) {
        self.hide(e);
        return false;    
    });

    this.$overlay.on("click",function(e) {
        self.hide(e);
        return false;
    });

    this.$next.on("click", function(e) {
        self.next(e);
        return false;
    });

    this.$prev.on("click", function(e) {
        self.prev(e);
        return false;
    });

    this.$window.on("load resize", function() {
        self.resize();
    });
};


Modal.prototype.show = function(e) {
    var $target = $(e.currentTarget),
        src=$target.attr("href");
    this.$contents.html("<img src=\"" + src +"\"/>");
    this.$container.fadeIn();
    this.$overlay.fadeIn();
    var index = $target.data("index");
    this.countChange = this.createCounter(index,this.$el.length);

    return false;
};

Modal.prototype.hide = function(e) {
    this.$container.fadeOut();
    this.$overlay.fadeOut();
};

Modal.prototype.slide = function(index) {
    this.$contents.find("img").fadeOut({
        complete: function() {
            var src = $("[data-index=\"" + index + "\"]").find("img").attr("src");
            $(this).attr("src",src).fadeIn();
        }
    });
};

Modal.prototype.createCounter = function(index, len) {
    return function(num) {
        return index = (index + num + len) % len;
    };
};

Modal.prototype.next = function() {
    this.slide(this.countChange( 1 ));
};

Modal.prototype.prev = function() {
    this.slide(this.countChange( -1 ));
};

Modal.prototype.resize = function() {
    var w = this.$window.width();
    if(w<640) {
        this.$container.css({"width":"320","height":"213"});
    } else {
        this.$container.css({"width":"750","height":"500"});
    }
};

$("#more-btn").on("click", function() {
    var html = "<li><a href=\"photo-04.jpg\" data-index=\"3\"><img alt=\"\" src=\"photo-04.jpg\" width=\"160\" class=\"img-thumbnail\"></a></li>";
    $(html).appendTo($("#modal-thumb")).hide().fadeIn();
    $(this).fadeOut();
    modal.$el = $("#modal-thumb a");
});

var modal = new Modal($("#modal-thumb a"));


Modalが実体化されるとプロトタイプオブジェクトプロパティinitializeのメソッドinitialize()が実行され、さらにinitialize()内でプロパティの初期化をおえるとhandleEventsが実行されます。
しかし、イベントが発生しないと何も始まらないので待機します。そしてModalを実体化したときに渡した実引数$("#modal-thumb a")や、initialize内で初期化したjqueryオブジェクトに渡したセレクタなどがクリックされたら、同じくModalのプロトタイプであるshowメソッドやhideメソッドなどにイベントオブジェクトを実引数として渡したうえで実行する、という流れになっております。

ここで質問です。このソース最下部で実体化したコンストラクタModalからinitializeを実行しさらにinitialize()内でプロパティの初期化をおえるとhandleEventsが実行されますが、イベントが発生しないと何も始まらないので待機します。
そしてModalを実体化したときに渡した実引数$("#modal-thumb a")や、initialize内で初期化したjqueryオブジェクトに渡したセレクタなどがクリックされたら、同じくModalのプロトタイプであるshowメソッドやhideメソッドなどにイベントオブジェクトを実引数として渡したうえで実行する、という流れですが、このソースの流れはjavascriptにおける公理(一種の決まりのようなもの)なのでしょうか。
つまりvarのように絶対付けないといけないわけではないが、付けないと後々に不具合のもととなるので任意で付けているように何かしらソースを構築する上でここにあれを、それをあそこにというような決まった、或いはそうしたほうがいいよね、というソースの流れがあるのでしょうか。このソースもそのような流れの公理があってそのようにしているのでしょうか。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

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

  • Lhankor_Mhy

    2017/08/26 11:29

    ご質問は、initializeメソッドやhandleEventsメソッドを、prototypeプロパティ下に置いているのはなぜか、ということですか?

    キャンセル

  • aaaaaaaa

    2017/08/28 19:30

    ご返答ありがとうございます。仰る通りです。質問文を見返しましたが、かなり分かりづらいものとなっておりましたので修正しました。

    キャンセル

回答 2

checkベストアンサー

+6

このソースの流れはjavascriptにおける公理(一種の決まりのようなもの)なのでしょうか

こういう考え方は好ましくない、と私は思っています。
この手の話題では https://okwave.jp/qa/q5081024.html のKI401さんの言葉を思い出します。

別に法律で規制されてるわけでもなし、使用しては「いけない」ことはないと思う。
単に、普通ならこんな汚染ライブラリ使いたくないよね?ってだけのハナシ。
  じゃ「使いたくない」って、それはなぜか?
  保守性が悪くなるからだ。
バグの原因になるからだ。

重要なのは、「なぜそのコードが推奨/非推奨なのか」を理解していることです。
極論をいえば、仕組みが分かっていれば何を使っても良いのです。
仕組みが分かっている人は、良いコードを自分で考えて導き出すでしょう。
そういう人は「公理だから」という理由ではなく、「~という理屈から保守性が高くなるから」のような理由でコードの書き方を選択します。

初心者向けに「理屈はいいからこういうコードを書け」と教えることもあると思いますが、それは初めだけで、いずれは理屈も理解して貰わなければ困ります。

長くなりましたが、答えを書きます。
Modalからinitializeを実行するのは公理ではありません。
この書き方は後で initialize() を実行し直す事で初期化をやり直せることを意図したものですが、インスタンスから作り直しても良いので、この書き方に拘る必要はありません。
そもそも、this.$el しか初期化し直さないのなら、直接書き換えても同じです。

Re: aaaaaaaa さん

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/08/29 19:43

    ご返答ありがとうございました。

    >>この書き方は後で initialize() を実行し直す事で初期化をやり直せることを意図したものですが、
    質問文には、表記し忘れておりましたがこのソースは、勉学用の書籍で作ったものです。しかし、書籍には
    initializeを実行し直すことで…という内容は書いておりませんでしたので、なるほどと思いました。

    つまりinitialize()で初期化したプロパティたちが、何らかの処理で別の値を代入されてもinitialize()を再度実行すれば
    元に戻る(最初に初期化したときの値が代入される)、ということを狙った、というか想定したソースだということですよね。

    キャンセル

  • 2017/08/29 23:25 編集

    > 書籍には initializeを実行し直すことで…という内容は書いておりませんでしたので、なるほどと思いました。
    多分、考え方の問題になるのだと思います。
    書籍に全て書いてある事はおそらくありませんが、「自分が書く場合ならどうだろう」「この書き方と他の書き方を比較検討してみたら、各々の長所/短所は何だろう」とシミュレーションしてみる事で見えてくるものはあります。

    > つまりinitialize()で初期化したプロパティたちが、何らかの処理で別の値を代入されてもinitialize()を再度実行すれば元に戻る(最初に初期化したときの値が代入される)、ということを狙った
    なるほど、「元に戻る」という発想が私にはありませんでした。
    その考え方でいく場合、問題となるのは Modal.prototype.handleEvents の処理です。
    jQuery#on では新しい関数オブジェクトを指定している為、handleEvents() が呼び出される度に新しいイベントハンドラが定義される事になります。

    var modal = new Modal($("#modal-thumb a"));
    modal.initialize($("#modal-thumb a"));

    このコードによって各イベントハンドラは2回ずつ発動されることになり、意図しない動作となります。
    期待通りにリセットする為には各々のイベントハンドラを jQuery#off で削除してから initialize() を呼び出す必要があります。
    イベントハンドラ周りの再初期化が考えられているコードではないと思います。
    個人的な感想としては良い出来のコードとはいえないので、Lhankor_Mhy さんが仰るように、コンストラクタパターンの一つとして読み、細かな書き方はご自身でいろんなパターンのコードを書いて試していく事をお勧めします。
    aaaaaaaa さんは書籍を引用した質問をよくしていますが、自分で書いたコードの質問があまりないので、実際に書いた経験が少ないのではと感じています。
    全てが分からなくてもいいのでご自身で書いてみる事は良い経験になると思います。

    キャンセル

  • 2017/08/30 19:42

    ご返答ありがとうございました。大変助かりました。
    確かに書籍に頼りすぎるのではなく自分の頭を動かして記述することも大事ですね。phpは、だいぶそうなってきました。javascriptはまだまだ書籍の助けも必要ですが、貴重なご意見の通りにやってみようかなとも思います。

    キャンセル

+1

おそらく、公理とは「デザインパターン」のことを言ってるのだと思います。
この書き方は、javascriptにおける「コンストラクタパターン」の標準的な書き方に沿っているかと思います。
「JavaScriptデザインパターン コンストラクタパターン」でググってみるといいのでは。

JavaScriptのパターン コンストラクタパターン - @ledsun blog
ステップアップのためのJavascriptデザインパターン入門(2) - コンストラクタパターン - イソップブログ
JavaScript のクラス定義

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/08/28 15:57

    よく見ると、3つ目のリンク先のコードはよくないですね。

    キャンセル

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

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

関連した質問

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