21

他のライブラリとの名前の競合を防ぐために、JavaScript コードを「名前空間」にパッケージ化できるようにしたいと考えています。名前空間の宣言は単純なコードである必要があるため、この機能を提供するために外部ライブラリに依存したくありません。これを簡単に行う方法についてさまざまなアドバイスを見つけましたが、 JSLintを (「The Good Parts」オプションを使用して)実行したときにエラーが発生しないように見えるものはありません。

例として、高度な JavaScript (YUI を使用しない名前空間のセクション)からこれを試しました。

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

これをJSLintで実行すると、次のエラーが発生します。

Problem at line 2 character 12: 'MyNamespace' is not defined.
Problem at line 3 character 5: 'MyNamespace' is not defined.
Implied global: MyNamespace 2,3

「暗黙のグローバル」エラーは、明示的に宣言することで修正できますMyNamespace...

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}

...その他の 2 つのエラーは、変数を if ブロックの外で宣言することで修正できます。

"use strict";
var MyNamespace;
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

それでうまくいきますが、(MyNamespaceチェックされた時点で常に未定義になるので)それははるかに単純なものと同等です:

"use strict";
var MyNamespace = {};

JSLintはこれで満足していますが、名前空間として正しく機能しなくなるほどコードを単純化したことを懸念しています。この最終的な定式化は理にかなっていますか?

4

6 に答える 6

19

JSLint の言葉を真に受けないでください。書かれていることの多くは理にかなっていますが、クロックフォードの個人的なドグマもたくさん含まれています。特に、私はvar.

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    MyNamespace = {};
}

それはだめです。JSLint は、暗黙のグローバルについて不平を言うのは正しいです。'use strict'グローバルを暗示しないようにする必要があります。

"use strict";
if (typeof(MyNamespace) === 'undefined') {
    var MyNamespace = {};
}

それはいいです。var巻き上げられているので、存在し、コード ブロックに入るMyNamespaceと に設定されます。undefinedしたがって、存在しない変数を参照できるように(MyNamespace===undefined)するオペレーターの魔法の能力がなくても、そのテストを行うことができます。typeof

もう 1 つの方法は、明白なin演算子を使用することです (これは、存在するが に設定されている、存在しないプロパティを区別する唯一の方法ですundefined)。window通常のブラウザ スクリプトのグローバルの場合、グローバルオブジェクトに対して使用できます。

'use strict';
if (!('MyNamespace' in window)) {
    window.MyNamespace = {};
}

(JSLint もそれを好まない。「ブラウザを仮定する」というのは、何か計り知れない理由で定義されていないように見えるからだwindow。ヘイホー。)

于 2010-02-20T12:05:32.817 に答える
7

もっと短いバージョンを試すことができます:

var MyNamespace = MyNamespace || {};

これは、厳密モードであっても、JavaScript の名前空間が機能することが期待できるように、名前が既に存在する場合はその名前を使用し、存在しない場合は作成することで、JSLint で有効である必要があります。

于 2011-02-15T00:38:54.263 に答える
3

構文を介してグローバル変数にアクセスできるwindow["NAMEOFGLOBAL"]ため、代わりに次のようにチェックできます。

if(typeof(window['MyNamespace']) === 'undefined') {
于 2010-02-20T11:09:20.957 に答える
1

私は以前にこの問題に遭遇しました。最終的なフォームは、定義された変数のチェックを完全にバイパスし、既に格納されている場合でも常に空のオブジェクトに上書きされるため、絶対に使用したくありません。

名前空間を作成するには、最後から2番目の形式が最も適切だと思いますが、実際には最初の形式も適切です。JSLintが報告するエラーは、私の意見では一種のキャッチ22であり、それほど心配する必要はありません。宣言を省略しても大したことではないと思う理由は、名前空間前の時点でロードされた場合、JSLintの「変数が定義される前に使用された」というエラーが発生するためです。本質的には、ある警告を別の警告と交換するだけです。

于 2010-02-20T11:14:00.467 に答える
1

確かに、未定義チェックのポイントは、ユーザーが既存の名前空間を二重にロードしたり上書きしたりしていないことを確認することです。そういうわけで、私はあなたが行き過ぎたと思います。

どうですか:

var MyNs;
if(MyNs==null){
    //foo()
}
于 2010-02-20T11:05:19.260 に答える