4

私は「より良い」JavaScriptを書き込もうとしています。

以下は私が見つけて採用しようとしているパターンの1つです。しかし、私はその使用法について少し混乱しています。

たとえば、「ジョブ」というページがあるとします。そのページのJS機能は、次のようにカプセル化されます。

window.jobs = (function(jobs, $, undefined){
    return {
        addNew: function(){
            // job-adding code
        }
    }
})(window.jobs|| {}, jQuery);

$(function(){
    $('.add_job').on('click', function(event){
        event.preventDefault();
        window.jobs.addNew();
    });
});

おそらく差し引くことができるように、私が行ったのは、匿名のイベントハンドラー関数内にあるすべてのコードを、グローバルジョブオブジェクトの関数の呼び出しに置き換えることだけです。変数の衝突の可能性を減らし、全体を少しすっきりさせた以外は、なぜそれが良いことなのかわかりませんが、それで十分です。

-おそらくかなり明白な-質問は次のとおりです。イベントをバインドするinitタイプのものはすべて、まだ私の光沢のある新しいジョブオブジェクトの外にあります。どこにあるべきですか?ジョブオブジェクト内?jobsオブジェクト内のreturnオブジェクト内?init()関数の内部?

シンプルな機能を組み込むための安定した基本的なフレームワークを理解しようとしています。JSアプリを作成しているのではなく、現在よりも少し堅牢で保守しやすいコードを記述したいと思います。ありとあらゆる提案を歓迎します:)

4

4 に答える 4

2

アプリケーションを好きな数のmodules/に分割objectsすることもできます。

たとえば、すべてのDOMノードをキャッシュして定義する別のオブジェクト/モジュールと、イベントを処理するだけの別のオブジェクト/モジュールを持つことができます。たとえば、次のようになります。

(function ( win, doc, $, undef ) {
    win.myApp = win.myApp || { };

    var eventHandler = {
        onJobClick: function( event ) {
            event.preventDefault();
            myApp.addNew();
        }
    };

    var nodes = (function() {
        var rootNode = $( '.myRootNode' ),
            addJob = rootNode.find( '.add_job' );

        return {
            rootNode: rootNode,
            addJob: addJob
        };
    }());

    $(function() {
        myApp.nodes.addJob.on( 'click', myApp.handler.onJobClick );
    });

    myApp.nodes = nodes;
    myApp.handler = eventHandler;
}( this, this.document, jQuery ));

この (モジュール) パターンでシングルトンをリテラル、コンストラクター、またはその他としてどのように作成するかは問題ではありませんObject.create()。要件に適合する必要があります。

ただし、必要な数の特定のモジュール/オブジェクトを作成するようにしてください。もちろん、これらのシングルトン/モジュール/オブジェクトを複数の JavaScript ファイルに分割し、それらをオンデマンドでロードすることがさらに理にかなっており、ナイフと言う前に、モジュラー プログラミング パターンの世界にいてrequireJS、AMD または CommonJS モジュールを扱っています。 .

于 2012-07-24T15:02:28.783 に答える
1

あなたが現在行っている方法は、まさに私が行っている方法でもあります。通常、無名関数自体の内部でウィンドウ オブジェクトを作成し、その内部で宣言します (この場合は jClass = window.jClass)。

(function (jClass, $, undefined) { 

    /// <param name="$" type="jQuery" />

    var VERSION      = '1.31';
    UPDATED_DATE = '7/20/2012';

    // Private Namespace Variables
    var _self         = jClass; // internal self-reference
    jClass        = window.jClass; // (fix for intellisense)
    $             = jQuery; // save rights to jQuery (also fixes vsdoc Intellisense)

    // I init my namespace from inside itself
    $(function () {
        jClass.init('branchName');
    });

    jClass.init = function(branch) {
      this._branch = branch;
      this._globalFunctionality({ globalDatePicker: true });
      this._jQueryValidateAdditions();

      //put GLOBAL IMAGES to preload in the array
      this._preloadImages( [''] );

      this._log('*******************************************************');
      this._log('jClass Loaded Successfully :: v' + VERSION + ' :: Last Updated: ' + UPDATED_DATE);
      this._log('*******************************************************\n');
};

    jClass._log = function() {
    //NOTE: Global Log (cross browser Console.log - for Testing purposes)
    //ENDNOTE 

    try { console.log.apply(console, arguments); }  
    catch (e) {
        try { opera.postError.apply(opera, arguments); }
        catch (e) { /* IE Currently shut OFF : alert(Array.prototype.join.call(arguments, ' '));*/ }
    }   
};

}(window.jClass= window.jClass|| {}, jQuery));

このように完全に匿名のままにしておく理由は、別のファイルで、この jClass にさらに多くの機能を追加したいと考えているからです。私は単に別のものを作成します:

(function jClass, $, undefined) {

jClass.newFunction = function (params) {
    // new stuff here
};

}(window.jClass = window.jClass || {}, jQuery))

ご覧のとおり、私は object.object 表記を好みますが、オブジェクト リテラル object : object を使用できます。それはあなた次第です!

いずれにせよ、これらすべてを個別に残し、実際のページ ロジックなしでカプセル化することで、これを globalJS ファイル内に簡単に配置し、サイトのすべてのページで使用できるようになります。以下の例のように。

jClass._log('log this text for me');

モデルロジックをビジネスロジックと絡み合わせたくないので、2つを分離する正しい道を歩み、グローバルな名前空間/クラス/などをより柔軟にすることができます!

于 2012-07-24T15:02:21.890 に答える
1

カプセル化に関しては、問題addNewありません。jQuery クロージャーで宣言するだけでも、グローバル スコープを回避できます。あなたが得ているのは、MVC アーキテクチャに近いものを実装することだと思います。

私が好きなことは、DOM 要素でインスタンス化するオブジェクトを作成し、独自のバインディングを処理したり、コントロールなどにアクセスするためのメソッドを提供したりすることです。

例:

   // (pretend we're inside a closure already)
   var myObj = function(args){
       this.el = args.el; // just a selector, e.g. #myId
       this.html = args.html;
       this.bindings = args.bindings || {};
   }

   myObj.prototype.appendTo = function(elem){
       elem.innerHTML += this.html;
       this.bindControls();
   };

   myObj.prototype.remove = function(){
       $(this.el).remove(); // using jQuery
   };

   myObj.prototype.bindControls = function(){
       for(var i in this.bindings){ // event#selector : function
           var boundFunc = function(e){ return this.bindings[i].call(this,e); };
           $(this.el).on(i,boundFunc);
       }
   }; 
于 2012-07-24T15:00:28.563 に答える
0

ここでモジュール パターンに関する包括的な研究を見つけることができます: http://www.adequatelygood.com/JavaScript-Module-Pattern-In-Depth.htmlブロッ​​ク スコープのモジュール アプローチのすべての側面をカバーしています。ただし、実際には、コードをカプセル化するかなりの数のファイルが必要になるため、問題はそれらをどのように組み合わせるかです。AMD... モジュールのロードごとに生成される複数の HTTP リクエストは、ページの応答時間に悪影響を及ぼします。そのため、ブラウザー内での使用に適した単一の JavaScript ファイルにコンパイルされた CommonJS を使用できます。いかに簡単か見てみましょうhttp://dsheiko.github.io/cjsc/

于 2014-08-05T11:48:09.667 に答える