web-dev-qa-db-ja.com

実際の例でjavascriptモジュールパターンを使用する方法は?

JavaScriptモジュールパターンを理解しようとしています。どうあるべきかという例を見てきましたが、使い方がわかりません。

たとえば、ここではいくつかのことが起こっています。

_$('input#share').on("click", function() {

    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
        $("#messageempty").jmNotify();
        $('.remove_loading').remove();
    } else {
        addMessage(message);
    }

    return false;
});


function addMessage(message)
{
    $.ajax({
        url: '/test',
        type: 'POST',
        dataType: "json",
        data: {'message' : message},
        success: function(data) {
                ...
        },
        error: function() {
            ...
        }
    });
}
_

上記の例を次のように使用するにはどうすればよいですか?

_var myTest = function() {
    var selectId;
    function addMessage () {
        // ...
    }
    return { // public interface
        publicMethod1: function () {
            // all private members are accesible here
        }
    };
};
var start = myTest();
_

クリックイベントをどこに追加し、変数を宣言し、ajax呼び出しでaddMessage関数を追加しますか。 addMessage関数を呼び出しますか?すべてを$(document).ready(function()でラップする必要がありますか?

誰かが私のためにこれにいくつかの光を当てることができますか?

ありがとう

12
Patrioticcow

これはかなり意見の分かれるテーマですが、私は(あなたの完全なアプリとそれが何をするのかを完全に知らなくても)それをやります。

var myApp = (function() {

  var someElement = $("#foo"); //some element I know I'll use lots

  var addMessage = function(message) {
    $.ajax({
      url: '/test',
      type: 'POST',
      dataType: "json",
      data: {'message' : message},
      success: function(data) {
              ...
      },
      error: function() {
          ...
      }
    });
  };

  var inputClick = function(event) {
    event.preventDefault();
    //depending on if you'll reuse these selectors throughout the app I might have these as variables
    $('.loading').html('<img class="remove_loading" src="/graphics/loading.gif" />');

    var message = $(".wallmessage").val();

    if (message == ""){
      $("#messageempty").jmNotify();
      $('.remove_loading').remove();
    } else {
      addMessage(message);
    }
  };

  var bindFunctions = function() {
    $("input#share").on("click", inputClick)
  };

  var init = function() {
    bindFunctions();
  };

  return {
    // EDIT: 27/12/16 - need to return init for 'usage' example to work
    init: init,
    addMessage: addMessage
    //anything else you want available
    //through myApp.function()
    //or expose variables here too
  };


})();

//usage

myApp.init();

パターンの元のコードが間違っています。関数をすぐに呼び出される関数にするには、関数の最後に()が必要です。 )、次に実行し、return statementを介してすべてを公開します。

私がやったこととは少し違うことを望むかもしれません。それは基本的な考えにすぎませんが、それがあなたを始めるのに役立つことを願っています。

しばらく前に誰かがこのパターンに関連する質問をしました 私はそれに答えました なぜ(function() {})();を使用するのか、そしてreturnステートメントがそのコンテキストでどのように機能するのかを説明します。読む価値があるかもしれません。

20
Jack Franklin

明らかにするモジュールパターンは次のように使用されます。

var moduleName = (function () {
    var privateVariable = 'private';

    var privateMethod = function () {
        alert('this is private');
    };

    // this is the "revealed" part of the module
    return { 
        publicVariable: 'public',
        publicMethod: function () {
            alert('this is public');
        }
    };
}());

パブリック変数/メソッドをプライベートとして定義してから、それらへの参照を公開してパブリックにすることもできます。これは好みの問題です。

あなたの例では、addMessageをモジュールの一部にしたい場合は、次のようにします。

var moduleName = (function () {
    // this becomes public due to the reference exposure in the return below
    var addMessage = function () {
        // do whatever
    };

    // this is the "revealed" part of the module
    return { 
        addMessage: addMessage
    };
}());

moduleName.addMessage();
12
jbabey

Javaとは異なり、Javascriptには、プロパティまたはメソッドに関するプライベートおよびパブリックの概念がありません。 firstNameとlastNameの2つのプロパティを持つpersonというオブジェクトを作成し、プロパティのゲッターとなる2つの関数も作成しましょう。 Javascriptでは、オブジェクトのプロパティとして関数を作成できます。これらの関数には、他のプロパティと同じようにどこからでもアクセスできます。

var person={
  "firstName":"Anoop",
  "lastName":"Rai",
  "getFirstName":function(){
    return this.firstName;
  },
  "getLastName":function(){
    return this.lastName;
  }
};
console.log(person.getFirstName());
console.log(person.firstName);

上記の予想通り、コード11はAnoopとAnoopを出力します。うーん、それはオブジェクト指向のプログラミングには適していません。ゲッターの実装に成功したので、パブリックスコープのセッターも必要です。プロパティはプライベートスコープとしてマークする必要があります(これらのプライベートおよびパブリックの概念はJava、C++のような言語に属します)。私たちの意図は良いです。Javascriptに固有の概念を適用しましょう。 person.firstNameは実行したくないので、プロパティに直接アクセスできないようにします。 Javaのような言語では、プライベートとパブリックのために、プロパティの制御されたアクセスを実現しましたが、Javascriptではすべてがパブリックです。

Javascriptは、クロージャの概念を使用して、プライベートやパブリックなどを実装します。このパターンはモジュールパターンと呼ばれます。つまり、パブリックアクセスから変数を非表示にします。スコープを実装するには、コードを関数でラップします(スコープは、Javascriptの関数を介して実装されることに注意してください)。

function createPerson(){
  var returnObj={
    "firstName":"Anoop",
    "lastName":"Rai",
    "getFirstName":function(){
      return this.firstName;
    },
    "getLastName":function(){
      return this.lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

また、上記の行には、AnoopとAnoopが印刷されています。それでも成功しません。プロパティがオブジェクトに関連付けられている限り、オブジェクトには直接アクセスされます。それを解きましょう。プロパティの代わりに、関数スコープの変数(クロージャ変数)を作成します。

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
console.log(person.firstName);

上記の行は、Anoopとundefinedを出力します。これはどのように起こりますか?クロージャのため、関数getFirstNameおよびgetLastNameが作成されたとき、関数はスコープチェーン全体を持っているか、関連する変数(firstNameおよびlastName)へのポインターを言います。オブジェクトreturnObjは変数を記憶していませんが、クロージャのために関数オブジェクトは記憶しています。目的を達成したように見えますが、1つ残っているのは、firstNameとlastNameの制御されたアクセスのセッターです。セッターを実装しましょう。

function createPerson(){
  var firstName="Anoop";
  var lastName="Rai";
  var returnObj={
    "getFirstName":function(){
      return firstName;
    },
    "getLastName":function(){
      return lastName;
    },
    "setFirstName":function(name){
      return firstName=name;
    },
    "setLastName":function(name){
      return lastName=name;
    }
  };
  return returnObj;
}
var person=createPerson();
console.log(person.getFirstName());
person.setFirstName("Kumar");
console.log(person.getFirstName());

FirstNameは正常に変更されましたが、制御された方法で変更されました。

http://jkoder.com/the-module-pattern-javascript-way-of-hiding-data-in-objects-from-public-access/

1
Anoop Rai

アイデアは、コードをセグメント/モジュールに分割することで、外界からの可視性を減らし、コード管理を改善することです。モジュラー設計パターンの本当に良い使用法と、私たちが利益を得る方法を知りたい場合は、これをチェックしてください。それ。
http://learn.jquery.com/code-organization/concepts/

1
kta

私はMootoolsの経験がありますが、jQueryの初心者です。ドキュメントを読みましたが、コードを整理する最も賢い方法はモジュールパターンのようですので、試してみます。ただし、IIFE内の各変数は自己完結型のオブジェクトであるため(しゃれは意図されていません)、そのスタイルに欠けているように見えることの1つは「自己」の概念です。

それで...多分これは目的全体を打ち負かします、しかしあなたはこのようなことをすることができます、そしてそれでもモジュールパターンスタイルが有効であるすべての方法でそれを「有効」にすることができますか?

var feature = ( function () {

    var self = {

        config: {
            option1: 'thing 1',
            option2: 'thing 2'
        },


        init: function (options) {

            // allow overriding the default config
            jQuery.extend( self.config, options );

            self.doSomething();

        },

        doSomething: function () {

        },

    };

    return {
        init: self.init
    }

})();

これについて私が気に入っているのは、「self」を使用してすべてのメソッドとプロパティを内部的に参照できることです。 「return」オブジェクトを使用して必要なメソッドを公開することはまだできるので、(おそらく)それで問題ありません。しかし、私はそのような初心者であり、これは非常にシンプルで(一見)エレガントに見えるので、大きな落とし穴を見逃しているに違いありません。これは、私がMootoolsでよく知っているObjectLiteral形式とコーディングスタイルを共有しています。だから多分私は丸いペグを四角い穴に合わせようとしています。 「self.doSomething()」ではなく、「doSomething」とだけ言うことができるので、内部オブジェクトリテラルは必要ないかもしれません。そうですか?

$ .ajaxの「context」引数を「self」に設定できるので、部分的にこれが好きです。これは勝利のようです。

0
hairbo