4

JavaScriptの名前空間を作成する際に注意する必要がある危険性や警告はありますか?JavaScriptネームスペースの使用に関連する危険性はありますか?

私たちのプロジェクトはかなり広範で、私たちは多くのJavaScriptファイル(20以上、もっと期待しています)を実行しています。これは、名前空間を使用せずに任意のコードの保守性を持つことは不可能であるので、我々はそうのようにそれらを実装している:

をそして階層を作成するために、我々はそうのようにそれらをリンク:これは正常に動作します

var globalNamespace = { 
    functions1: namespace1, 
    functions2: namespace2, 
    ... 

} 

、 JSが名前空間を持っているかのように動作させるのは本質的に「トリック」です。このメソッドは多く使われていますが、これに関するほとんどの文献は、それを行う方法に焦点を当てているようであり、可能性のある欠点があるかどうかはわかりません。より多くのJSコードを書くと、これはすぐにシステムの仕組みの不可欠な部分になっています。したがって、シームレスに動作することが重要です。

この「誘発された」名前空間システムがエラーを引き起こしたり、特別な注意が必要な状況がありましたか?すべてのブラウザで同じ動作が期待できますか?

+3

一般的に、名前空間は衝突の問題を解決しません。階層を1レベル上に移動するだけです。他の人が無関係のプロジェクトでも 'namespace1'を使うことができなくなってしまいました。 –

+2

これは非常に基本的なJavaScriptのセマンティクスに基づいています。それについては危険な、あるいは特に "賢い賢い"ものはありません。私の意見では、これは機能を収集して公開する方法としても非常に弱い方法です。 – Pointy

+1

「私的な」変数を導入する予定があるのは唯一の本当の「つかまえ」です。 – Tejs

答えて

3

あなたの例では、名前空間を定義する方法、あなたがwindow.namespace1を切り詰め何かを持っているのであれば、それはまたwindow.globalNamespace.namespace1

を壊しますあなたは

window.namespace1 
window.namespace2 
window.globalNamespace 
window.globalNamespace.namespace1 
window.globalNamespace.namespace2 

で終わるように、各名前空間のうち、グローバルを作成するように見えます編集:

は、ここでは、この問題を回避得た方法は次のとおりです。

namespacing = { 
    init: function(namespace) { 
     var spaces = []; 
     namespace.split('.').each(function(space) { 
      var curSpace = window, 
       i; 

      spaces.push(space); 
      for (i = 0; i < spaces.length; i++) { 
       if (typeof curSpace[spaces[i]] === 'undefined') { 
        curSpace[spaces[i]] = {}; 
       } 
       curSpace = curSpace[spaces[i]]; 
      } 
     }); 
    } 
}; 

次に、あなたはこのようにそれを使用する:あなたは新しいグローバル変数を導入する必要はありません、あなたは自信を持って、その中に他のオブジェクトをつかうことなく、既存の名前空間に追加することができます

namespacing.init('globalNamespace.namespace1'); 

globalNamespace.namespace1.doSomething = function() { ... }; 

この方法です。

+0

はい、わかっていました。これを防ぐためのガイドラインがあります。私は、たとえ互いがぶつかり合っていなくても、同じ名前のコンポーネントを望んでいません。 – Goro

+0

私は間違っているかもしれませんが、私はこの例ではこれは問題ではないと信じています。オブジェクトは参照渡しであり、namespace1はオブジェクトなので、定義と割り当ての間に「clobbered」がない限り、あなたは大丈夫です。 – Asmor

+0

@Goroのコーディングガイドラインは、他の人やサードパーティのベンダーなどとはあまり意味がありません。 – Asmor

2

基本的にオブジェクトとそのオブジェクトに他のオブジェクトに関数を追加しているので、それぞれのブラウザで同じように処理すると思います。

しかし、モジュール性が必要な場合は、require.jsのような(比較的)単純なフレームワークを使用してみませんか?それはあなたとあなたのチームはモジュール方式でコードを書くことができ、必要に応じこれらのモジュールのインポート」にチームを可能にします:

require(["helper/util"], function() { 
    //This function is called when scripts/helper/util.js is loaded. 
}); 
Require.jsは、依存関係の世話をします、そしてそれはまた、汚染防止します

グローバル名前空間。

+0

はい、require.jsを使用して調べています:) – Goro

+0

あなたの最初の考えは何ですか?あなたが採用するのは簡単でしょうか、あるいは多くのコードをリファクタリングする必要がありますか? –

+0

私たちのコードはすでにかなりモジュール化されているので、比較的簡単であるはずです。 – Goro

1

私たちは職場でも同様のシステムを使用しています。私はそこに欠点があるとは思わない。それは単なるオブジェクトとプロパティです。同じ理由から、クロスブラウザの互換性は良いはずです。特定の関数(例えば、Foo.Bar.Test.Namespace2.Function)に解決するためにいくつかの長い名前を書く必要がなくなりますが、その前に変数に代入することで解決できます。

1

これは私がそれを行うことをお勧めしますので、あなたは "ベース"名前空間を除いてグローバルスコープから完全に離れています。私たちは私が働いているところで似たようなことをしますAcme coの仕事をして、ACMEをベースネームスペースにしたいとしましょう。すべてのファイルの先頭に

、あなたは、と思います:

if (!window.ACME) { window.ACME = {} } 

を次にあなただけに行くとあなたがその面で好き定義します。

ACME.Foo = { 
    bar: function() { console.log("baz"); } 
} 

名前空間のレベルをもっと深くしたい場合は、各レベルで同じことをします。

if (!window.ACME) { window.ACME = {} } 
if (!ACME.Foo) { ACME.Foo = {} } 

各ファイルが独立してテストすることができ、それらは自動的に名前空間のインフラストラクチャを設定しますが、あなたはそれらを一緒にコンパイルしたり、同時に複数のファイルをテストする場合、彼らはすでにあるものを上書きしておくません場合は、この方法定義された。

関連する問題