2008-08-16 11 views
13

私は頻繁にJavaScriptで名前空間を使用するための「簡潔な」方法はありますか?

namespaces = { com : { example: { example.com's data} } 

のラインに沿って「名前空間」構造の内側に自分のjavascriptのすべてを置くサイトに遭遇しました。しかし、他の名前空間の枠組みに関して安全にこれを設定することは、比較的多額の量を必要とするように思わましたコード(> 2行として定義されています)。誰かがこれを行うための簡潔な方法を知っているかどうか疑問に思っていましたか?それを構造化するための比較的標準的な一貫した方法があるかどうか?例えば。グローバルオブジェクトに直接接続された "com"名前空間か、名前空間オブジェクトを介して接続されていますか?

[編集:whoops、明らかに、{com = { ... } }は、私が意図したものに近いものを達成できませんでした。Shog9に感謝します。 :D]

答えて

19

Javascriptにはスタンドアロンの名前空間がありません。それには、名前を解決するスコープと、指定されたスコープ内でアクセス可能な名前付きデータに貢献できるオブジェクトを提供できる関数があります。ここで

を修正、あなたの例です:

var namespaces = { com: { example: { /* example.com's data */ } } } 

これは、オブジェクトリテラルを割り当てられている変数namespacesです。オブジェクトには1つのプロパティ、com、1つのプロパティを持つオブジェクト:example、おそらく何か興味深いオブジェクトが含まれています。

だから、namespaces.com.exampleのようなものを入力できます。 somePropertyOrFunctionOnExampleそれはすべて動作します。もちろん、それはまたばかげている。あなたは階層的な名前空間を持っていません。実際に気にしているものを含むオブジェクトを含むオブジェクトを持っています。

var com_example_data = { /* example.com's data */ }; 

これは、無意味な階層なしでも同様に機能します。

com_example = com_example || {}; 
com_example.flags = com_example.flags || { active: false, restricted: true}; 

com_example.ops = com_example.ops || (function() 
    { 
     var launchCodes = "38925491753824"; // hidden/private 
     return { 
     activate: function() { /* ... */ }, 
     destroyTheWorld: function() { /* ... */ } 
     }; 
    })(); 

...で、私見で、合理的に簡潔な:あなたが実際には、階層を構築したい場合は今

は、あなたはこのような何かを試すことができます。

+1

今 'com_example'はグローバルオブジェクトの一部になるだろう、けれども。 'com_something_else'、' com_etc'のように多くのオブジェクトを追加したとしたら、グローバルオブジェクトのルートレベルを汚染しています。他のすべてのオブジェクトが追加されたグローバルでただ1つの 'com'オブジェクトがあれば、それは好ましくないでしょうか?また、複数のライブラリが使用されている場合、既存のオブジェクトを上書きすることはありません。 – Peter

+2

@Peter:複数のライブラリで同じシンボルが定義されている場合は、何が問題であろうとも、そのため、jQueryのようなライブラリは、すべてのものを1つのグローバルオブジェクトにまとめるのに、そのような長さになります。私の要点は、複数のトップレベルオブジェクトを使用すべきではなく、深くネストされたオブジェクトを持つネームスペースを偽装するだけで、狂ったオブジェクト名よりも何も買わないということでした。もっと実用的な方法については私の最後の例を参照してください。衝突する可能性の低い単一のグローバル名を使用し、異種のコードでオブジェクトを追加する技術です。 – Shog9

3

YUI libraryライブラリには、望ましいと思われる機能を使用して名前空間を処理するコードがあります。他のライブラリもこれを行うかもしれません。

12

ここでは、Peter Michauxの興味深い記事がJavascript Namespacingです。彼は、Javascriptの名前空間の異なる3種類について説明します。

  1. プレフィックス名前空間を
  2. 私は彼がここで言っ盗用ではないでしょうが、私は彼の記事があると思い

名前空間

  • ネストされたオブジェクトの名前空間
  • 単一オブジェクト非常に有益。

    Peterも、パフォーマンスに関する考慮事項がいくつかあることを指摘しています。この話題は、新しいECMAScript Harmony計画が名前空間とパッケージングのための4.0計画を削除したことを考えると面白いと思います。

  • 6

    私は、グローバルなスコープ内に単一の親オブジェクトを作成してすべてを含むというYahooの慣習に従います。ドットの代替またはアンダースコアとして

    var FP = {}; 
    FP.module = {}; 
    FP.module.property = 'foo'; 
    
    1

    、あなたはドル記号使用することができます既存のオブジェクトを上書きしないことを確認するために

    var namespaces$com$example = "data"; 
    
    +0

    これはどのようなメリットをもたらしますか? – eyelidlessness

    +0

    このようにすると、ネストされた内部オブジェクトを持つオブジェクトとしてネームスペースを定義する必要はありません。どこにでも名前を定義することができます。 –

    +0

    ドットやアンダースコアの代わりに$記号を使用する利点はまだありません。私は$記号がドットやアンダースコアよりも読むのが難しいと思う。 –

    5

    を、あなた必要がありますので、のようなもの:

    if(!window.NameSpace) { 
        NameSpace = {}; 
    } 
    

    または

    var NameSpace = window.NameSpace || {}; 
    

    この方法では、名前空間オブジェクトを上書きすることを心配することなく、これをアプリケーション/ Webサイトのすべてのファイルの先頭に置くことができます。また、これにより、各ファイルの単体テストを個別に記述することができます。

    1

    私はこの(source)も好き:

    (function() { 
        var a = 'Invisible outside of anonymous function'; 
        function invisibleOutside() { 
        } 
    
        function visibleOutside() { 
        } 
        window.visibleOutside = visibleOutside; 
    
        var html = '--INSIDE Anonymous--'; 
        html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
        html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
        contentDiv.innerHTML = html + '<br/><br/>'; 
    })(); 
    
    var html = '--OUTSIDE Anonymous--'; 
    html += '<br/> typeof invisibleOutside: ' + typeof invisibleOutside; 
    html += '<br/> typeof visibleOutside: ' + typeof visibleOutside; 
    contentDiv.innerHTML += html + '<br/>';​ 
    
    0

    オブジェクトリテラルとthisオブジェクトまたは関数が含まれているローカル変数の兄弟プロパティに基づいて名前空間を行うには、明示的な名前のいずれかを使用してください。たとえば、次のように

    var foo = { bar: function(){return this.name; }, name: "rodimus" } 
     
    var baz = { bar: function(){return this.name; }, name: "optimus" } 
     
    
     
    console.log(foo.bar()); 
     
    console.log(baz.bar());

    または明示nameプロパティなし:

    var foo = { bar: function rodimus(){return this; } } 
     
    var baz = { bar: function optimus(){return this; } } 
     
    
     
    console.log(foo.bar.name); 
     
    console.log(baz.bar.name);

    またはthisを使用しない:

    var foo = { bar: function rodimus(){return rodimus; } } 
     
    var baz = { bar: function optimus(){return optimus; } } 
     
    
     
    console.log(foo.bar.name); 
     
    console.log(baz.bar.name);

    その後、チェックを行うためにhasOwnPropertyテストを使用し、変数や他の一般的な名称に対抗するために名前のプロパティを追加するRegExpまたはObjectコンストラクタ関数を使用します。

    var foo = RegExp(/bar/); 
     
        
     
    /* Add property */ 
     
    foo.name = "alpha"; 
     
    
     
    document.body.innerHTML = String("<pre>" + ["name", "value", "namespace"] + "</pre>").replace(/,/g, "&#09;"); 
     
    
     
    /* Check type */ 
     
    if (foo.hasOwnProperty("name")) 
     
        { 
     
        document.body.innerHTML += String("<pre>" + ["foo", String(foo.exec(foo)), foo.name] + "</pre>").replace(/,/g, "&#09;"); 
     
        } 
     
    
     
    /* Fallback to atomic value */ 
     
    else 
     
        { 
     
        foo = "baz"; 
     
        } 
     
    
     
    var counter = Object(1); 
     
    
     
    /* Add property */ 
     
    counter.name = "beta"; 
     
    
     
    if (counter.hasOwnProperty("name")) 
     
        { 
     
        document.body.innerHTML += String("<pre>" + ["counter", Number(counter), counter.name] + "</pre>").replace(/,/g, "&#09;"); 
     
        } 
     
    else 
     
        { 
     
        /* Fallback to atomic value */ 
     
        counter = 0; 
     
        }

    DOMは、HTMLのネームスペースに次の規則を使用しますそしてSVGエレメントインタフェース定義:

    • HTMLTitleElement
    • SVGTitleElement
    • SVGScriptElement
    • HTMLScriptElement

    JavaScriptのコアは、多型の単純な形態としてtoString方法を名前空間にプロトタイプを使用します。

    参照

    関連する問題