0

私は次のコードを持っています:

(function(){
...
var n = n || {};
...
})(); 

これは私が望むことを行い、nを{}に設定します。これは、これが初めて発生し、未定義になるためです。残念ながら、これは関数内にあるためn、範囲が関数に限定されており、他のスクリプトでは使用できません。

行をに変更したかったのn = n || {}ですが、エラーが発生しました: ReferenceError: n is not defined

n = {}期待どおりに機能するように変更します。しかし、これは私が望むものではありません。使用しないnと、の未定義がエラーを引き起こし、var期待どおりに機能する(ORステートメントの右側を取得するために使用される誤った値である)理由がわかりません。キーワードの理解に基づいて、var私はそれが両方であるか、どちらでもないことを期待します。

なぜvar問題なのか、ここで何が起こっているのか?

4

9 に答える 9

3

したがって、グローバル変数の作成に問題があるようです。

良い。

JavaScriptでグローバル変数を作成するのは、本来よりも簡単です。

あなたの問題はそれnが定義されていないということです(ええと)。まだ定義されていない変数を参照することはできません。varでも、「 ???を使ったバージョンとどう違うの?」とお考えかもしれません。そして、それは良い質問です。

JavaScriptは、変数定義の「巻き上げ」と呼ばれるものを実行します。関数内で変数を定義すると、その定義は暗黙的に関数の先頭に再配置されます。だからあなたが書いている間:

var n = n || {};

実際に起こったことは、より近いものでした。

var n;
n = n || {};

ただし、それはそれほど単純ではありません。そのコードを書き込もうとすると、n常にに設定されてしまうから{}です。しかし、一般的な本質はそこにあります。変数宣言は、割り当ての前に行われます。

を削除するとvar、巻き上げる宣言がなくなるため、参照エラーが発生します。したがって、「適切な」方法の1つ(グローバル変数を作成するのは「適切」ではないため、この用語を大まかに使用します)はvar、関数ラッパーの外に配置することです。そのようです:

var n = n || {};
(function () {
    //do stuff.
}()); 

残念ながら、次のようにすることはできません。

var n; 
(function () {
    n = n || {};
}());

これには、上記の例と同じ「問題」があります。nが他の場所で定義されている場合は、undefinedによって設定されてから、関数でvar n;に設定さ{}れます。関数の外部で宣言と割り当て全体を実行することにより、探しているものを取得できます。(質問のタイトルに基づいて)私が想定しているのは、実際には名前空間であり、任意のグローバル変数ではありません。それはいたずらだろう!;-)

アップデート:

ちなみに、これを行うためのより良い方法は、グローバルオブジェクトを明示的に参照することです。

(function (exports) {
    exports.n = exports.n || {};
}(this));

これはおそらく、node.jsのようなものや、コードをラップする可能性のあるもの($(function() { }))などでうまく機能します。

于 2012-09-24T19:15:24.337 に答える
2

未定義の変数と未定義の値を持つ定義済み変数の違いに遭遇しました。

未定義の変数を参照すると、例外が発生します(ReferenceError: n is not defined

未定義の値で定義された変数を参照することは問題なくfalse、条件でキャストされます。

これを回避するnには、オブジェクトのプロパティとして参照できwindowます。プロパティは未定義になることはなく、未定義の値のみを持つためです。

(function(){
...
window.n = window.n || {};
...
})(); 
于 2012-09-24T19:09:55.723 に答える
1

nはまだ宣言されていないので、ntrue-likeかどうかのチェックは機能しません。nまだ宣言されているかどうかを明示的に確認できます。

n = typeof n !== 'undefined' ? n : {};

しかし、それを見るのはあまり良くありません。グローバルスコープに何かを配置するには、関数のwindow.n代わりに使用するnか、関数の外部で宣言しnます。

var n;

(function(){
...
n = n || {};
...
})(); 
于 2012-09-24T19:09:52.437 に答える
1

1)小さな変更が役立ちます:

(function() {
    var n = window.n = window.n || {};
    // Code of your module...
    n.hello = function() {
        alert('Hello');
    };
})();

n.hello();

デモ

このようにして、関数内の同じオブジェクトへのnグローバル参照とローカル参照があります。n

2)次の方法で再設計することもお勧めします。

各モジュールを次のようにします。

var MyApplication = (function(app) {

    // Code of the module here...

    app.hello = function() {
        console.log('Hello!');
    };

    return app;
})(MyApplication || {});

MyApplication.hello();
于 2012-09-24T19:11:09.023 に答える
0

関数の最後に次のことを行います。

window.n = n;

これにより、nがグローバル名前空間に配置され、他のスクリプトで使用できるようになります。

于 2012-09-24T19:06:46.787 に答える
0

strictモードでは、グローバル名前空間を明示的に使用する必要があります。これは通常window、;です。使用する行を変更すると、window.n必要なものが得られるはずです。

window.n = window.n || {};
于 2012-09-24T19:07:46.507 に答える
0

var n;コードの前に追加すると、グローバルになりますn。関数に対してローカルにvarなるため、重要です。n

于 2012-09-24T19:07:55.163 に答える
0

varローカル変数を使用せずに作成すると、グローバル名前空間が汚染されます。ほとんどの場合、グローバル変数を作成したくないので、ブラウザはこれを防ぐ必要があります。

あなたができることはwindowオブジェクトを使用することです:

window.n = window.n || {}

ただし、これはブラウザ環境でのみ機能します。そうでない場合(たとえば、サーバーサイドJavaScriptを使用している場合)、次の方法でグローバルオブジェクトを取得します。

var global = (function getGlobal(){
    return (function(){
        return this;
    }).call(null);
}());

その後:

global.n = global.n || {};
于 2012-09-24T19:09:29.100 に答える
0

1)評価の最初のラウンドではvar n = n || {};、変数を作成します。

var n = undefined;

2)2回目の評価では、条件付きで値を設定します。

n = undefined || {};

3)varステートメントがないと、参照されている、どこにも存在しないvarがあります。

var myVar = non_existant_var; // error

varがすでに存在する場合、たとえば、グローバルスコープ、または現在の関数が内部にネストされている他の関数に存在する場合n、チェーンの途中で、見つかったものをすべて使用します。存在しない場合は、適合します。

したがって、コードに意図的に穴を開けるのではなく、アクセスしようとしているスコープをコードに認識させようとするのではなく、直接アクセスしてみませんか?

(function (name) {
    window[name] = window[name] || {}; // returns undefined and not reference error
    var ns = window[name];

    ns.init = function () {};
    // .............
    /* Don't return the application to a var -- it already exists in the global scope */
}("BigLongApplicationName"));

BigLongApplicationName.init(); // === window.BigLongApplicationName.init();
于 2012-09-24T19:23:04.507 に答える