3

Javascript 用のゲーム エンジン、または便利なクラスと関数の大規模なライブラリのようなものを作成しています。サーバー側とクライアント側の両方でいくつかの科学的シミュレーションに使用する予定なので、機能の範囲は非常に広くなりますが、常に仮想世界 (ゲームなど) を中心に展開します。

とはいえ、どうやって締めくくるのかわからない。すべてのクラスを提供するだけでは、グローバル名前空間が汚染されます。これは非常に悪いことです。名前空間として機能する 1 つのオブジェクト内にすべてを配置することはできますか? フレームワーク自体をインスタンス化できるクラスにする必要がありますか?

後者のオプションを選択した場合、クラス (コンストラクター関数) 内のクラスをどのように処理しますか?

var Engine = function()
{
    this.someVar = 4;
}

Engine.prototype.Scene = function()
{
    this.entities = [];
    //What if the scene object needs some classes that are in the engine? How does it get it's parent engine object?
}

Engine.prototype.Scene.prototype.render = function()
{
    //"this" should now represent an instance of a scene. But how can I get someVar from the engine? How can I traverse up in the hierarchy of classes?
}
4

2 に答える 2

2

私は、「公開モジュール」(... パターン)と呼ばれることがあるものを使用することを好みます。次のようになります。

var Engine = (function($)
{
    $ = $ || {};
    var someVar = 4;

    $.Scene = function()
    {
        this.entities = [];
    }

    $.Scene.prototype.render = function()
    {
        // this function can access someVar just fine because of JavaScript's scoping rules
    }

    return $;
})(Engine);

これは、即時起動関数式(以降、IIFEと呼びます) と呼ばれるものを使用して、Engine オブジェクト内でクロージャーを形成します。JavaScript の scope の処理により、someVarIIFE 内で定義された任意の関数にアクセスできます。ただし、IIFE で定義した関数someVarを参照したい場合、関数はそれ自体を定義できないということになります。someVar

魔法は return ステートメントから来ます。オブジェクトが返されることがわかります。このオブジェクト内で、「パブリック」にしたいものをすべて定義する必要があります。

Engine.Sceneコンストラクター、ユーティリティ メソッドなどは、コードを適切に名前空間化する を介してアクセスできます。

引数に関しては$、これはEngine各ファイルの関数に渡し、いくつかのメソッド/プロパティ/コンストラクターを追加 (または存在しない場合は新しいコンストラクターを作成) してから、戻り値を別の IIFE に渡してさらに処理できるようにするためです。拡張。

これは、jQuerydojoLimeJSなど、多くの一般的な JavaScript フレームワークで使用されている方法です。


シーン.js:

var Engine = (function ($) {
  // this creates a new object if Engine is undefined in the 
  // invocation below, and keeps the old object otherwise.
  // alternatively: if ($ === undefined) { $ = new Object; }
  $ = $ || {};

  $.foo = "foo";
  $.Scene = function () {
    // blah blah
  }

  // Engine holds either a newly created object,
  // or the old one if it was already defined
  return $;
})(Engine);

スプライト.js:

var Engine = (function ($) {
  $ = $ || {};

  $.Sprite = function () {
    // totally works
    this.bar = $.foo;
  }

  return $;
})(Engine);

次に、次のようなものでそれらを使用できます。

<script type="text/javascript" src="bar.js"></script>
<script type="text/javascript" src="foo.js"></script>
<script type="text/javascript">
  var mySprite = new Engine.Sprite;
  var myScene = new Engine.Scene;
</script>

$好きなもの、$$一般的なもの、または賢いものに置き換えることができます。これは、追加するグローバル オブジェクトの単なるプレースホルダーです。

于 2012-07-30T09:23:01.817 に答える