JavaScriptでのコード編成に関する一般的に受け入れられているベストプラクティス[終了]


561

jQueryのようなJavaScriptフレームワークがクラ​​イアント側のWebアプリケーションをよりリッチで機能的にするので、1つの問題に気づき始めました...

世界でこれをどのように整理しますか?

  • すべてのハンドラを1つの場所に配置し、すべてのイベントの関数を記述しますか?
  • すべての機能をラップする関数/クラスを作成しますか?
  • 狂ったように書いて、それがうまくいくことを願っていますか?
  • あきらめて、新しいキャリアを得る?

jQueryについて言及しましたが、これは実際には一般的なJavaScriptコードです。何行にもわたっていくと、スクリプトファイルの管理や探しているものを見つけるのが難しくなります。私が見つけた最大の問題は、同じことを実行する方法が非常に多く、現在一般に受け入れられているベストプラクティスがどれであるかを知るのが難しいことです。

.jsファイルをアプリケーションの他の部分と同じようにきれいに保つための最良の方法に関する一般的な推奨事項はありますか?それともIDEの問題ですか?そこに良いオプションはありますか?


編集

この質問は、ファイル編成ではなく、コード編成に関するものでした。ファイルをマージしたりコンテンツを分割したりする良い例がいくつかあります。

私の質問は、実際にコードを整理するために現在一般的に受け入れられているベストプラクティスの方法は何ですか?あなたの方法は何ですか、またはページ要素とやり取りして、互いに競合しない再利用可能なコードを作成するための推奨される方法は何ですか?

一部の人々は、良い考えである名前空間をリストしました。より具体的にはページ上の要素を処理し、コードを整理して整理する他の方法は何ですか?


:実際に彼はCONCATENATEに使用しています&彼のJSファイルを圧縮「だけ」何のツール、コードの組織自体について話すには時間がない取った誰かstackoverflow.com/questions/16736483/...を
エイドリアンはして

回答:


183

javascriptに名前空間が組み込まれていると、はるかに便利ですが、Dustin Diazがここで説明しているように整理すると、非常に役立ちます。

var DED = (function() {

    var private_var;

    function private_method()
    {
        // do stuff here
    }

    return {
        method_1 : function()
            {
                // do stuff here
            },
        method_2 : function()
            {
                // do stuff here
            }
    };
})();

私は異なる「名前空間」を置き、時には個別のクラスを別々のファイルに入れました。通常私は1つのファイルから始め、クラスまたは名前空間がそれを保証するのに十分な大きさになると、それを独自のファイルに分離します。ツールを使用してすべてのファイルをプロダクション用に結合することも優れたアイデアです。


24
私は通常「クロックフォードウェイ」と呼んでいます。私からの+1
マット・ブリッグス

4
さらに少し先に進むこともできます。:このリンクを参照してくださいwait-till-i.com/2007/08/22/...
MKroehnert

4
@MattBriggsは別の方法で呼ばれ、module patternそれはに基づいていIIFE patternます。
Adrien Be

どういうわけかクラスをエクスポートする必要はありませんか?このようなモジュールの外部からオブジェクトを作成するにはどうすればよいですか?またはcreateNewSomething()、戻りオブジェクトにメソッドがあるべきで、オブジェクトの作成はモジュール内でのみ発生しますか?うーん...クラス(コンストラクタ)は外部から見えると思います。
robsch

@robsch彼の例はパラメータを取りませんが、ほとんどは取ります。これが通常どのように行われるかについては、ここの私の例を参照してください(TypeScript、ただし99%は同じです): repl.it/@fatso83/Module-Pattern-in-TypeScript
オリゴフレン

88

HTMLにJavaScriptを含めないようにしています。すべてのコードはクラスにカプセル化され、各クラスは独自のファイルにあります。開発の場合、各jsファイルを含めるための個別の<script>タグがありますが、HTTPリクエストのオーバーヘッドを削減するために、これらは本番環境用の単一の大きなパッケージにマージされます。

通常、アプリケーションごとに1つの「メイン」jsファイルがあります。したがって、「survey」アプリケーションを作成している場合、「survey.js」というjsファイルがあります。これには、jQueryコードへのエントリポイントが含まれます。インスタンス化中にjQuery参照を作成し、それをパラメーターとしてオブジェクトに渡します。これは、JavaScriptクラスが「純粋」であり、CSS IDまたはクラス名への参照を含まないことを意味します。

// file: survey.js
$(document).ready(function() {
  var jS = $('#surveycontainer');
  var jB = $('#dimscreencontainer');
  var d = new DimScreen({container: jB});
  var s = new Survey({container: jS, DimScreen: d});
  s.show();
});

また、読みやすさのために命名規則が重要であると思います。例:すべてのjQueryインスタンスの前に「j」を付加します。

上記の例では、DimScreenというクラスがあります。(これにより、画面が暗くなり、警告ボックスがポップアップするものとします。)画面を覆うために拡大できるdiv要素が必要であり、警告ボックスを追加するため、jQueryオブジェクトを渡します。jQueryにはプラグインの概念がありますが、実際の利点がないため、制限があるように見えます(たとえば、インスタンスは永続的ではなく、アクセスできません)。したがって、DimScreenクラスは、たまたまjQueryを使用する標準のJavaScriptクラスになります。

// file: dimscreen.js
function DimScreen(opts) { 
   this.jB = opts.container;
   // ...
}; // need the semi-colon for minimizing!


DimScreen.prototype.draw = function(msg) {
  var me = this;
  me.jB.addClass('fullscreen').append('<div>'+msg+'</div>');
  //...
};

このアプローチを使用して、かなり複雑なアプリケーションをいくつか作成しました。


15
$変数名の接頭辞として使用する方が一般的であることがわかりましたが、間違っている可能性があります。したがって、の$s = $('...')代わりにjS = $('...')、好みの問題だと思います。興味深いことに、ハンガリー語の表記はコードのにおいであると考えられています。私のJavaScriptコードの規則/設定の一部がC#/ Javaのコーディング規則とどのように異なるかは奇妙です。
jamiebarrow 2011

9
@jamieこの場合、コードのにおいではありません。ハンガリー語が優れている数少ないケースの1つです。あなたはこれを読みたいかもしれません。
Dan Abramov、2011年

3
@DanAbramovリンクありがとうございます。私は本当にジョエルのブログをすべて読む必要があります、彼は物事をとてもよく説明します。間違いなく彼の名声/評判に値する。私はこれからSystems HungarianコードのにおいApps Hungarianとして、そして練習として参照します:)
jamiebarrow

C#の世界ではvar、の使用を促進するための優れた記事になるかもしれません。使用に対するほとんどの議論varは、返されるものの「タイプ」がわからないところですが、引数は返されるものの「クラス」を知らないほうがいいと思います。Apps Hungarianを使用している場合、その心配はありません。興味深いです。
jamiebarrow 2011年

3
@Marnen:要点はわかりますが、プログラマーへのガイドとしては無意味ではありません。接頭辞$は、後でコードを読み取るときにそれが何であるかを思い出させ、それにより、より迅速な理解に役立ちます。
Sean

39

スクリプトを開発用に別々のファイルに分割し、それらをまとめて「リリース」バージョンを作成し、YUI Compressorまたはそれに類似したものを実行できます。


不要なJavaScriptスクリプトがある場合があります。それらをクライアントに送信するのは無駄です。必要なものだけを送ることだと思います。もちろん、イントラネットアプリなど、終日使用されているWebアプリの場合、最初のページの読み込み時にバッチ全体を一度に送信することをお勧めします。
DOK

2
@DOKコンパイルには、未使用のものの削除が含まれている必要があります。
aehlke

帯域幅の必要性を試し、減らすための遅延読み込みの概念もあります。最初のページを読み込んでから、必要なスクリプトファイルの非同期読み込みを実行します(この質問に対する他の回答で説明されています)。しかし、それはより多くの要求を必要とするかもしれず、実際にはあまり使えないかもしれません。@ DOK、JSがキャッシュされている場合、1つの中程度のリクエストがいくつかの小さなリクエストよりも優れている場合があります。
jamiebarrow 2011

27

以前私がコピーしたポストに触発Rakefileベンダーと分散ディレクトリWysiHat(RTEは、変更ログが言及)及びコードチェックに含めるいくつかの変更を行っJSLint有すると縮小YUIコンプレッサー

アイデアは、Sprockets(WysiHatから)を使用して複数のJavaScriptを1つのファイルにマージし、マージされたファイルの構文をJSLintで確認して、配布前にYUI Compressorで縮小することです。

前提条件

  • Javaランタイム
  • ルビーとレーキの宝石
  • JARをクラスパスに配置する方法を知っている必要があります。

さあ

  1. Rhinoをダウンロードし、JAR( "js.jar")をクラスパスに配置します
  2. YUI Compressorをダウンロードし、JAR(build / yuicompressor-xyz.jar)をクラスパスに配置します。
  3. WysiHatをダウンロードし、「vendor」ディレクトリをJavaScriptプロジェクトのルートにコピーします
  4. JSLint for Rhinoをダウンロードして、「vendor」ディレクトリに配置します

次に、JavaScriptプロジェクトのルートディレクトリに「Rakefile」という名前のファイルを作成し、次のコンテンツを追加します。

require 'rake'

ROOT            = File.expand_path(File.dirname(__FILE__))
OUTPUT_MERGED   = "final.js"
OUTPUT_MINIFIED = "final.min.js"

task :default => :check

desc "Merges the JavaScript sources."
task :merge do
  require File.join(ROOT, "vendor", "sprockets")

  environment  = Sprockets::Environment.new(".")
  preprocessor = Sprockets::Preprocessor.new(environment)

  %w(main.js).each do |filename|
    pathname = environment.find(filename)
    preprocessor.require(pathname.source_file)
  end

  output = preprocessor.output_file
  File.open(File.join(ROOT, OUTPUT_MERGED), 'w') { |f| f.write(output) }
end

desc "Check the JavaScript source with JSLint."
task :check => [:merge] do
  jslint_path = File.join(ROOT, "vendor", "jslint.js")

  sh 'java', 'org.mozilla.javascript.tools.shell.Main',
    jslint_path, OUTPUT_MERGED
end

desc "Minifies the JavaScript source."
task :minify => [:merge] do
  sh 'java', 'com.yahoo.platform.yui.compressor.Bootstrap', '-v',
    OUTPUT_MERGED, '-o', OUTPUT_MINIFIED
end

すべてを正しく行った場合は、コンソールで次のコマンドを使用できるはずです。

  • rake merge -異なるJavaScriptファイルを1つにマージする
  • rake check-コードの構文をチェックします(これはデフォルトのタスクなので、単に入力できますrake
  • rake minify -JSコードの縮小バージョンを準備する

ソースのマージについて

Sprocketsを使用すると、require他のJavaScriptファイルをインクルード(または)できるJavaScriptプリプロセッサーになります。次の構文を使用して、初期ファイル( "main.js"という名前ですが、Rakefileで変更できます)から他のスクリプトを含めます。

(function() {
//= require "subdir/jsfile.js"
//= require "anotherfile.js"

    // some code that depends on included files
    // note that all included files can be in the same private scope
})();

その後...

WysiHatに付属のRakefileを見て、自動化された単体テストをセットアップしてください。いい従業員 :)

そして今、答えのために

これは元の質問にあまりよく答えません。知って申し訳ありませんが、他の誰かが混乱を整理するのに役立つと思いますので、ここに投稿しました。

この問題に対する私のアプローチは、可能な限り多くのオブジェクト指向モデリングを行い、実装を異なるファイルに分離することです。その場合、ハンドラーは可能な限り短くする必要があります。Listシングルトンの例もいい例です。

そして名前空間...まあ、より深いオブジェクト構造によって模倣することができます。

if (typeof org === 'undefined') {
    var org = {};
}

if (!org.hasOwnProperty('example')) {
    org.example = {};
}

org.example.AnotherObject = function () {
    // constructor body
};

私は模造品の大ファンではありませんが、グローバルスコープの外に移動したいオブジェクトがたくさんある場合に役立ちます。


18

コードの編成には、規則とドキュメント標準の採用が必要です
。1.物理ファイルの名前空間コード。

Exc = {};


2.これらの名前空間のJavaScriptでクラスをグループ化します。
3.実世界のオブジェクトを表すためのプロトタイプまたは関連する関数またはクラスを設定します。

Exc = {};
Exc.ui = {};
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};
Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    ...
};


4.規則を設定してコードを改善します。たとえば、すべての内部関数またはメソッドをオブジェクトタイプのクラス属性にグループ化します。

Exc.ui.domTips = function (dom, tips) {
    this.dom = gift;
    this.tips = tips;
    this.internal = {
        widthEstimates: function (tips) {
            ...
        }
        formatTips: function () {
            ...
        }
    };
    ...
};


5.名前空間、クラス、メソッド、変数のドキュメントを作成します。必要に応じて、コードの一部についても説明します(FIとForsの中には、通常、コードの重要なロジックを実装するものがあります)。

/**
  * Namespace <i> Example </i> created to group other namespaces of the "Example".  
  */
Exc = {};
/**
  * Namespace <i> ui </i> created with the aim of grouping namespaces user interface.
  */
Exc.ui = {};

/**
  * Class <i> maskdInput </i> used to add an input HTML formatting capabilities and validation of data and information.
  * @ Param {String} mask - mask validation of input data.
  */
Exc.ui.maskedInput = function (mask) {
    this.mask = mask;
    ...
};

/**
  * Class <i> domTips </i> used to add an HTML element the ability to present tips and information about its function or rule input etc..
  * @ Param {String} id - id of the HTML element.
  * @ Param {String} tips - tips on the element that will appear when the mouse is over the element whose identifier is id <i> </i>.
  */
  Exc.ui.domTips = function (id, tips) {
    this.domID = id;
    this.tips = tips;
    ...
};


これらはほんの一部のヒントですが、コードの編成に大いに役立ちました。成功するには規律が必要です。


13

優れたOO設計原則と設計パターンに従うことは、コードの保守と理解を容易にするための長い道のりです。しかし、私が最近発見した最高のものの1つは、パブリッシュ/サブスクライブとも呼ばれるシグナルとスロットです。 簡単なjQuery実装については、http://markdotmeyer.blogspot.com/2008/09/jquery-publish-subscribe.htmlご覧ください

このアイデアは、他の言語でGUI開発によく使用されています。コードのどこかで重要なことが発生すると、他のオブジェクトの他のメソッドがサブスクライブする可能性があるグローバル合成イベントを公開します。これにより、オブジェクトの分離が良好になります。

Dojo(およびPrototype?)には、この手法の組み込みバージョンがあると思います。

シグナルとスロットとは何ですか?も参照してください


これはjQueryで行いました。JSにはイベントモデルが組み込まれているため、フレームワークのサポートはそれほど必要ありません。
Marnen Laibow-Koser 2013


11

Dojoには、初日からモジュールシステムがありました。実際、それはDojoの土台であると考えられており、それをすべて一緒に保持する接着剤です。

モジュールDojoを使用すると、次の目的が達成されます。

  • Dojoコードとカスタムコードのネームdojo.declare()スペース()—グローバルスペースを汚染せず、他のライブラリーとユーザーの非Dojo対応コードと共存します。
  • 名前でモジュールを同期または非同期でロードします(dojo.require())。
  • モジュールの依存関係を分析して、単一のファイルまたは相互依存ファイルのグループ(いわゆるレイヤー)を作成し、Webアプリケーションに必要なものだけを含めることにより、カスタムビルドを構築します。カスタムビルドには、Dojoモジュールと顧客提供のモジュールも含めることができます。
  • Dojoおよびユーザーのコードへの透過的なCDNベースのアクセス。AOLとGoogleはどちらもこの方法でDojoを使用していますが、一部の顧客はカスタムWebアプリケーションに対しても同じようにしています。

9

JavasciptMVCを調べてください。

あなたはできる :

  • コードをモデル、ビュー、コントローラーの各レイヤーに分割します。

  • すべてのコードを単一の製品ファイルに圧縮する

  • コードを自動生成

  • 単体テストを作成して実行する

  • そしてもっとたくさん...

何よりも、jQueryを使用しているため、他のjQueryプラグインも利用できます。


うん、私はjmvcを使用しましたが、それはかなり良いです-ドキュメントはもっと良いかもしれません
meouw

9

私の上司は、彼らがモジュラーコード(C言語)を書いたときのことを今でも語っています。プログラマーはどのフレームワークでもアセンブリーを作成できると言われています。コード組織を克服するための戦略は常に存在します。基本的な問題は、JavaScriptをおもちゃとして扱い、決して習得しない人にあります。

私の場合、適切なinit_screen()を使用して、UIテーマまたはアプリケーション画面ベースでjsファイルを書き込みます。適切なid命名規則を使用して、ルート要素レベルで名前空間の競合がないことを確認します。控えめなwindow.load()では、トップレベルのIDに基づいて、物事を結び付けます。

私は、Javaスクリプトのクロージャーとパターンを厳密に使用して、すべてのプライベートメソッドを非表示にしています。これを行った後、プロパティ/関数定義/変数定義の競合の問題に直面することはありませんでした。ただし、チームで作業する場合、同じ厳密さを強制することはしばしば困難です。


9

誰もMVCフレームワークについて言及していないことに驚いています。私はBackbone.jsを使用してコードをモジュール化および分離してきましたが、それは非常に貴重です。

これらの種類のフレームワークは数多くありますが、そのほとんどは非常に小さいものです。私の個人的な意見では、派手なUIに対応するためにjQueryを数行以上書く場合や、リッチなAjaxアプリケーションが必要な場合は、MVCフレームワークを使用すると作業がはるかに簡単になります。


8

「狂ったように書いて、うまくいくことを願っていますか?」このようなプロジェクトをたった2人の開発者が開発して保守している、たくさんのJavaScriptコードを含む巨大なアプリケーションを目にしました。その上、考えられるすべての可能なjquery関数にさまざまなショートカットがありました。コードをプラグインとして整理することをお勧めします。これは、jqueryがクラス、モジュール、名前空間などのユニバース全体に相当するためです。しかし、事態はさらに悪化し、プロジェクトで使用される3行のコードのすべての組み合わせを置き換えるプラグインの作成を開始しました。個人的にjQueryは悪魔だと思います。多くのJavaScriptを含むプロジェクトではjQueryを使用しないでください。怠惰になり、コードを整理することを決して考えないようにするためです。40のチェーンされたjQuery関数を含む1行ではなく、100行のJavaScriptを読みたい(私は m冗談ではありません)。一般に信じられていることとは逆に、名前空間やクラスと同等のJavaScriptコードを構成するのは非常に簡単です。それがYUIと道場の仕事です。必要に応じて、自分で簡単にロールできます。YUIのアプローチの方がはるかに効率的です。しかし、有用なものを書きたい場合は、通常、YUIの命名規則を補うためのスニペットをサポートする優れたエディターが必要です。


3
本当に長い連鎖コマンドについては私も同感ですが、jQueryの優れた点の1つは、すべてのJavaScriptをHTMLから除外することです。要素にIDやon <whatever>イベントを追加する必要がないので、すべての要素のイベントハンドラーをセットアップできます。いつものように、ツールの過剰使用は悪いことです...
Hugoware 2008

私はjQueryで組織化された巨大なプロジェクトに取り組んできました。それが組織の邪魔になると思う理由がわかりません。
Marnen Laibow-Koser、2011

7

私は実際に画面上で数回インスタンス化する必要のないすべてのものに対してシングルトンを作成します。それ以外のすべてのクラスです。そして、それらすべては同じファイルの同じ名前空間に置かれます。すべてにコメントが付けられ、UML状態図で設計されています。JavaScriptコードにはHTMLが含まれていないため、インラインJavaScriptはなく、ブラウザ間の問題を最小限に抑えるためにjqueryを使用する傾向があります。


3
良いコメントが鍵です-あなたがそれを言ったので私はする必要がなかったのでうれしいです。一貫性のある命名規則を追加します。これは、変数と簡単に理解できる、ある種の変数の編成戦略です。関数、およびあなたが述べたように、クラスとシングルトンの賢明な使用。
matt lohkamp 2008年

いいえ。コメントが必要な場合、コードは一般的に十分に読みにくいです。コメントを必要としないコードを書くように努めてください。
Marnen Laibow-Koser、2011

また、UMLと状態図が必要な場合は、おそらく、アーキテクチャがコードから十分に明確でないことを意味します。反対投票。
Marnen Laibow-Koser 2013

1
@Marnen適切に作成されたプロジェクトには、WHYではなくWHYを説明するコメントが含まれています。コードはすでにWHATを記述していますが、多くの場合、WHYを記述するために何かが必要です。賛成票。
Cypher

@Cypher適切に作成されたプロジェクトには、「何を」だけでなく、通常「なぜ」を伝えるのに十分なほど明確なコードがあります。コードと同期しているとは限らないため、コメントに「理由」を教えてもらえません。コード自体をドキュメント化します。
Marnen Laibow-Koser 2014

6

私の最後のプロジェクト-Viajeros.com-では、いくつかの手法を組み合わせて使用​​しました。Webアプリの構成方法がわからない-Viajerosは、明確に定義されたセクションを備えた旅行者向けのソーシャルネットワーキングサイトです。

私は、サイトセクションに従って、名前空間シミュレーションとモジュールの遅延読み込みを使用しています。各ページの読み込みで「vjr」オブジェクトを宣言し、常にそれに一連の共通関数(vjr.base.js)を読み込みます。次に、各HTMLページは、必要なモジュールをシンプルで決定します。

vjr.Required = ["vjr.gallery", "vjr.comments", "vjr.favorites"];

Vjr.base.jsは、サーバーからgzipで圧縮された各ファイルを取得して実行します。

vjr.include(vjr.Required);
vjr.include = function(moduleList) {
  if (!moduleList) return false;
  for (var i = 0; i < moduleList.length; i++) {
    if (moduleList[i]) {
      $.ajax({
        type: "GET", url: vjr.module2fileName(moduleList[i]), dataType: "script"
      });
    }
  }
};

すべての「モジュール」は次の構造を持っています:

vjr.comments = {}

vjr.comments.submitComment = function() { // do stuff }
vjr.comments.validateComment = function() { // do stuff }

// Handlers
vjr.comments.setUpUI = function() {
    // Assign handlers to screen elements
}

vjr.comments.init = function () {
  // initialize stuff
    vjr.comments.setUpUI();
}

$(document).ready(vjr.comments.init);

私のJavascriptの知識が限られていることを考えると、これを管理するためのより良い方法がなければならないことはわかっていますが、今までのところ、それは私たちにとって非常にうまく機能しています。


6

JQuery中心のNameSpaceの方法でコードを編成すると、次のようになります...プロトタイプやExtのような他のJavascript APIとも競合しません。

<script src="jquery/1.3.2/jquery.js" type="text/javascript"></script>
<script type="text/javascript">

var AcmeJQ = jQuery.noConflict(true);
var Acme = {fn: function(){}};

(function($){

    Acme.sayHi = function()
    {
        console.log('Hello');
    };

    Acme.sayBye = function()
    {
        console.log('Good Bye');
    };
})(AcmeJQ);

// Usage
//          Acme.sayHi();
// or
// <a href="#" onclick="Acme.sayHi();">Say Hello</a>


</script>

お役に立てれば。


これは私を小さなカーゴカルティとして感じます。jQueryコンストラクター関数の新しいインスタンスを実際に返すため、jQuery.fnはへのポインターです。「プラグイン」をjQueryに追加するということは、単にそのプロトタイプを拡張することを意味します。しかし、あなたがしていることはそれではなく、同じことを達成するためのより明確な方法があります。jQuery.prototype$()
Adam Lassek、2011年

彼は単に静的関数を作成していると思います。jQueryのドキュメントで、静的関数を宣言するこの方法は受け入れられることを覚えています
Alex Heyd

6

OO + MVCの優れたプリンシパルは、複雑なjavascriptアプリの管理に間違いなく役立ちます。

基本的に、私は自分のアプリとJavaScriptを次のような使い慣れたデザインに整理しています(これは、デスクトッププログラミングの時代からWeb 2.0までずっと存在します)。

JS OOおよびMVC

画像の数値の説明:

  1. アプリケーションのビューを表すウィジェット。これは拡張可能で、適切に分離されている必要があります。ウィジェットをスパゲッティコードに変換するのではなく、MVCが適切に分離しようとします(Webアプリケーションでは、JavaScriptの大きなブロックを直接HTMLに配置するのと同じです)。各ウィジェットは、他のウィジェットによって生成されたイベントをリッスンすることによって他のウィジェットを介して通信し、管理不能なコードにつながる可能性のあるウィジェット間の強い結合を減らします(スクリプトタグ内のグローバル関数を指すすべての場所にonclickを追加する日を覚えていますか?ああ...)
  2. ウィジェットに入力し、サーバーにやり取りするデータを表すオブジェクトモデル。データをモデルにカプセル化することにより、アプリケーションはデータ形式にとらわれなくなります。例:当然のことながら、JavascriptではこれらのオブジェクトモデルのほとんどがJSONにシリアル化および逆シリアル化されますが、何らかの理由でサーバーが通信にXMLを使用している場合、変更が必要なのはシリアル化/逆シリアル化レイヤーを変更することだけであり、必ずしもすべてのウィジェットクラスを変更する必要はありません。 。
  3. ビジネスロジックとサーバーへの通信を管理するコントローラークラス+場合によってはキャッシュレイヤー。この層は、サーバーへの通信プロトコルを制御し、必要なデータをオブジェクトモデルに入れます。
  4. クラスは、対応する名前空間にきちんとラップされています。私たちは皆、JavaScriptでいかに厄介なグローバル名前空間がどのようになり得るかを知っていると確信しています。

以前は、ファイルを独自のjsに分離し、一般的な方法を使用してJavascriptでOOの原則を作成していました。私がすぐに見つけた問題は、JS OOを書く方法が複数あり、すべてのチームメンバーが同じアプローチを持っているとは限らないことです。チームが大きくなると(私の場合は15人を超える)、オブジェクト指向のJavascriptに対する標準的なアプローチがないため、これは複雑になります。同時に、私は自分のフレームワークを作成したくないし、自分が解決したよりも賢い人だと確信している作業の一部を繰り返したくありません。

jQueryはJavascriptフレームワークとして信じられないほど素晴らしいですが、私はそれが大好きですが、プロジェクトが大きくなるにつれて、特にOOプラクティスの標準化を促進するために、Webアプリに追加の構造が明らかに必要です。私自身、いくつかの実験の後、YUI3ベースとウィジェット(http://yuilibrary.com/yui/docs/widget/http://yuilibrary.com/yui/docs/base/index.html)インフラストラクチャがまさに私が必要とするもの。私がそれらを使用するいくつかの理由。

  1. 名前空間のサポートを提供します。コードのOOおよびきちんとした編成の真の必要性
  2. クラスとオブジェクトの概念をサポートします
  3. クラスにインスタンス変数を追加する標準化手段を提供します
  4. 綺麗にクラス拡張に対応
  5. コンストラクタとデストラクタを提供します
  6. レンダリングとイベントバインディングを提供します
  7. ベースウィジェットフレームワークを持っています
  8. 各ウィジェットは、標準のイベントベースのモデルを使用して互いに通信できるようになりました
  9. 最も重要なことは、すべてのエンジニアにJavascript開発のためのオブジェクト指向標準を提供することです。

多くのビューとは異なり、私は必ずしもjQueryとYUI3のどちらかを選択する必要はありません。これら2つは平和的に共存できます。YUI3は私の複雑なWebアプリに必要なOOテンプレートを提供しますが、jQueryは私たち全員が使い慣れた使いやすいJS抽象化をチームに提供します。

YUI3を使用して、ベースをモデルとして拡張するクラス、ウィジェットをビューとして拡張するクラス、そして必要なロジックとサーバー側の呼び出しを行うコントローラークラスがあるコースを分離して、MVCパターンを作成することに成功しました。

ウィジェットは、イベントベースのモデルを使用して相互に通信し、イベントをリッスンし、事前定義されたインターフェースに基づいて必要なタスクを実行できます。簡単に言うと、OO + MVC構造をJSに配置することは私にとって喜びです。

免責事項ですが、私はYahoo!で働いていません。そして単に、元の質問によって提起された同じ問題に対処しようとしている建築家。誰かが同等のOOフレームワークを見つけたら、これもうまくいくと思います。主に、この質問は他のテクノロジーにも当てはまります。私たちのプログラミングの日をより管理しやすくするためにOO原則+ MVCを思いついたすべての人々に神に感謝します。


5

私が使用Dojoのパッケージ管理dojo.requiredojo.provide)と(クラスのシステムdojo.declareの別々のファイルに私のクラス/ウィジェットの全てをモジュール化しても、単純な複数の継承が可能になります)。これにより、コードが整理されたままになるだけでなく、クラス/ウィジェットの読み込みを遅延/ジャストインタイムで行うことができます。


3

数日前、37SignalsのスタッフがRTEコントロールをリリースしましたがひねりを加え。彼らは、一種のプリプロセッサコマンドを使用してjavascriptファイルをバンドルするライブラリを作成しました。

私はそれを使ってJSファイルを分離し、最後にそれらを1つにマージしています。このようにして、懸念事項を分離し、最終的に、パイプを通過するファイルを1つだけ(gzip圧縮された、それ以下)にすることができます。

テンプレートに、開発モードかどうかを確認し、個別のファイルを含めます。本番環境の場合は、最後のファイル(自分で「ビルド」する必要があります)を含めます。


1
getsprockets.orgが直接リンク
Matt Gardner、

3

偽のクラスを作成し、意味のある別の関数にスローできるものはすべてそうするようにしてください。また、コメントをたくさん付けて、スパゲッティコードを記述しないでください。すべてをセクションにまとめてください。たとえば、私の理想を描いた意味のないコードです。明らかに、実際の生活では、基本的にそれらの機能を含む多くのライブラリーも作成しています。

$(function(){
    //Preload header images
    $('a.rollover').preload();

    //Create new datagrid
    var dGrid = datagrid.init({width: 5, url: 'datalist.txt', style: 'aero'});
});

var datagrid = {
    init: function(w, url, style){
        //Rendering code goes here for style / width
        //code etc

        //Fetch data in
        $.get(url, {}, function(data){
            data = data.split('\n');
            for(var i=0; i < data.length; i++){
                //fetching data
            }
        })
    },
    refresh: function(deep){
        //more functions etc.
    }
};


2

これはおそらくDDD(ドメイン駆動設計)と結びついていると思います。私が取り組んでいるアプリケーションには、正式なAPIはありませんが、サーバー側のコード(クラス/ファイル名など)を介してそのようなヒントを提供します。それを武器に、問題ドメイン全体のコンテナーとしてトップレベルのオブジェクトを作成しました。次に、必要な場所に名前空間を追加しました。

var App;
(function()
{
    App = new Domain( 'test' );

    function Domain( id )
    {
        this.id = id;
        this.echo = function echo( s )
        {
            alert( s );
        }
        return this;
    }
})();

// separate file
(function(Domain)
{
    Domain.Console = new Console();

    function Console()
    {
        this.Log = function Log( s )
        {
            console.log( s );
        }
        return this;
    }
})(App);

// implementation
App.Console.Log('foo');

2

JavaScript組織の場合、以下を使用しています

  1. すべてのJavaScriptのフォルダー
  2. ページレベルのJavaScriptは、ページと同じ名前の独自のファイルを取得します。ProductDetail.aspxはProductDetail.jsになります
  3. ライブラリファイルのjavascriptフォルダー内にlibフォルダーがあります
  4. 関連するライブラリ関数を、アプリケーション全体で使用するlibフォルダーに配置します。
  5. Ajaxは、私がjavascriptフォルダーの外に移動して独自のフォルダーを取得する唯一のjavascriptです。次に、クライアントとサーバーの2つのサブフォルダを追加します
  6. クライアントフォルダーはすべての.jsファイルを取得し、サーバーフォルダーはすべてのサーバー側ファイルを取得します。

ファイル編成に最適です。私はそれをコードで行います。しかし、結局私は自分のコードをコンパイルします... dllとしましょう。JavaScriptでもこれが必要です。そうしないと、ページごとに15個のjsファイルを要求することになります。
10

ページごとに15個のJSファイルをリクエストしても問題はありません。ブラウザーはとにかく、後続のリクエストのためにそれらをキャッシュします。
Marnen Laibow-Koser、2011

@ MarnenLaibow-Koserページで15個のJSファイルを要求する場合の唯一の問題は、ブラウザーが一度に処理できるHTTP要求の数です。したがって、それらを1つのファイルにバンドルすると、ブラウザーが他の必要なファイルを同時に要求できるようになります。
iwasrobbされた2011年

それは事実ですが、最初の数回のヒットの後、それらはブラウザーのキャッシュに入れられるため、HTTP接続を必要としません。
Marnen Laibow-Koser、2011

2

私はこの小さなものを使っています。JSとHTMLテンプレートの両方に 'include'ディレクティブを提供します。混乱を完全に解消します。

https://github.com/gaperton/include.js/

$.include({
    html: "my_template.html" // include template from file...
})
.define( function( _ ){ // define module...
    _.exports = function widget( $this, a_data, a_events ){ // exporting function...
        _.html.renderTo( $this, a_data ); // which expands template inside of $this.

        $this.find( "#ok").click( a_events.on_click ); // throw event up to the caller...
        $this.find( "#refresh").click( function(){
            widget( $this, a_data, a_events ); // ...and update ourself. Yep, in that easy way.
        });
    }
});

2

あなたは使用することができますjqueryのMXあなたはモデル、ビュー、およびコントローラを使用することを可能にするスクリプトのセットです(javascriptMVCで使用します)。私はそれをプロジェクトで使用し、圧縮のために最小のスクリプトサイズで構造化されたJavaScriptを作成するのを助けました。これはコントローラーの例です:

$.Controller.extend('Todos',{
  ".todo mouseover" : function( el, ev ) {
   el.css("backgroundColor","red")
  },
  ".todo mouseout" : function( el, ev ) {
   el.css("backgroundColor","")
  },
  ".create click" : function() {
   this.find("ol").append("<li class='todo'>New Todo</li>"); 
  }
})

new Todos($('#todos'));

ビューとモデルパーツに関心がない場合は、jquerymx のコントローラーのみを使用することもできます。


1

あなたの質問は、昨年末に私を悩ませたものです。違い-プライベートメソッドとパブリックメソッドについて聞いたことがなかった新しい開発者にコードを渡す。シンプルなものを作らなければなりませんでした。

最終結果は、オブジェクトリテラルをjQueryに変換する小さな(約1KB)フレームワークでした。構文は視覚的に簡単にスキャンでき、jsが非常に大きくなった場合は、再利用可能なクエリを記述して、使用するセレクター、ロードされたファイル、依存関数などを見つけることができます。

ここに小さなフレームワークを投稿するのは実際的ではないので、例を使っブログ投稿を書きました(私の最初。これは冒険でした!)。ぜひご覧ください。

数分で確認できる他の人たちには、フィードバックをいただければ幸いです。

FireFoxは、オブジェクトクエリの例でtoSource()をサポートしているため推奨されます。

乾杯!

アダム


0

ほとんどのイベントハンドラーを格納するために、Ben Nolanの行動に触発されたカスタムスクリプトを使用します(残念ながら、これへの現在のリンクがもう見つかりません)。これらのイベントハンドラーは、たとえばclassNameまたはId要素によってトリガーされます。例:

Behaviour.register({ 
    'a.delete-post': function(element) {
        element.observe('click', function(event) { ... });
    },

    'a.anotherlink': function(element) {
        element.observe('click', function(event) { ... });
    }

});

グローバルな動作を含むものを除いて、ほとんどのJavascriptライブラリをオンザフライで含めるのが好きです。私はこれにZend FrameworkのheadScript()プレースホルダーヘルパー使用していますが、JavaScriptを使用して、たとえばAjile使用して他のスクリプトをその場ロードすることもできます。


これはあなたが探していたものですか?koders.com/javascript/...
DOK

うん、それはそれだ!:)リンクの背後にあるコードは、私が触発されたバージョンよりもかなり新しいようです。お疲れ様でした!
Aron Rotteveel 08

0

サーバー側の言語が何であるかについては言及しません。または、より適切には、サーバー側で使用しているフレームワーク(ある場合)。

IME、私はサーバー側で物事を整理し、それをすべてWebページに振り分けます。フレームワークには、すべてのページをロードする必要があるJSだけでなく、生成されたマークアップで機能するJSフラグメントを整理するタスクも与えられます。このようなフラグメントは通常、2回以上出力したくありません。そのため、フレームワークに抽象化されて、そのコードがその問題を管理します。:-)

独自のJSを発行する必要があるエンドページの場合、通常、生成されたマークアップに論理構造があることがわかります。そのようなローカライズされたJSは、多くの場合、そのような構造の開始時および/または終了時に組み立てることができます。

これによって効率的なJavaScriptを書くことが免除されないことに注意してください!:-)


弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.