「var FOO = FOO ||」とは {}」(変数または空のオブジェクトをその変数に割り当てる)はJavaScriptで意味しますか?


99

オンラインソースコードを見ると、いくつかのソースファイルの先頭でこれに遭遇しました。

var FOO = FOO || {};
FOO.Bar = …;

しかし、私は何がわからない || {}ができるのません。

私は知っている{}と等しいnew Object()と思います||は「すでに存在する場合はその値を使用し、それ以外の場合は新しいオブジェクトを使用する」のようなもののためます。

これがソースファイルの上部に表示されるのはなぜですか?


注:これは、JavaScriptソースファイルの上部に一般的に見られるコードパターンであることを反映するように質問が編集されました。
ロバートハーベイ

回答:


153

の意図に関するあなたの推測 || {}はかなり近いです。

ファイルの上部に表示されるこの特定のパターンは、名前空間を作成するために使用されます、つまり、グローバルオブジェクトを過度に汚染することなく関数と変数を作成できる名前付きオブジェクトます。

理由なぜそれが使われていますが、あなたが2つ(またはそれ以上)のファイルを持っている場合はそうあることです:

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func1 = {
}

そして

var MY_NAMESPACE = MY_NAMESPACE || {};
MY_NAMESPACE.func2 = {
}

それはその後、問題二つのファイルがロードされるためには、あなたはまだ取得していません、どちらも共有し、同じ名前空間のfunc1func2正しく内で定義されましたMY_NAMESPACEオブジェクトます。

最初にロードされたファイルにより初期オブジェクトが作成されMY_NAMESPACEその後ロードされたファイルによりオブジェクトが拡張されます。

便利なことに、これにより、同じ名前空間を共有するスクリプトの非同期読み込みが可能になり、ページの読み込み時間を改善できます。<script>タグにdefer属性セットがある場合、タグが解釈される順序がわからないため、上記で説明したように、この問題も修正されます。


2
これはまさにその通りです。最初にまったく同じ宣言を持ついくつかのjsファイルがあります。
リカルドサンチェス

41
行間を読み、それを行う理由を説明するための+1。ユーザーが求めたものだけでなく、ユーザーが実際に欲しかった答えを誰かが与えたとき、それは常に良いことです。:)
Spudley

1
私はそれがjavascriptの#ifndef /#defineだと言いたいです:)
Darren Kopp

1
||あなたはオプションの引数を提供したいとデフォルトにそれらを初期化するときに提供されていない場合にも本当に便利です:function foo(arg1, optarg1, optarg2) { optarg1 = optarg1 || 'default value 1'; optarg2 = optart2 || 'defalt value 2';}
crazy2be

1
@ crazy2beは、デフォルトが真の場合は機能しませんが、||演算子がundefinedから判断できないため、偽の値も有効falseyです。
Alnitak

23
var AEROTWIST = AEROTWIST || {};

基本的に、この行はAEROTWIST変数をAEROTWIST設定するか、空のオブジェクトに設定することを示しています。

ダブルパイプ ||はORステートメントであり、ORの2番目の部分は、最初の部分がfalseを返した場合にのみ実行されます。

したがって、AEROTWISTすでに値がある場合は、その値として保持されますが、まだ設定されていない場合は、空のオブジェクトとして設定されます。

これは基本的にこれを言うのと同じです:

if(!AEROTWIST) {var AEROTWIST={};}

お役に立てば幸いです。


1
JSにはブロックスコープがない
Alnitak

@Alnitak-ええ、あなたは正しいです。最近、クロージャーを使いすぎて、基本を忘れてしまいました。答えを編集します。
Spudley

6

||のもう1つの一般的な用途 未定義の関数パラメーターのデフォルト値も設定します。

function display(a) {
  a = a || 'default'; // here we set the default value of a to be 'default'
  console.log(a);
}

// we call display without providing a parameter
display(); // this will log 'default'
display('test'); // this will log 'test' to the console

他のプログラミングにおける同等のものは通常、次のとおりです。

function display(a = 'default') {
  // ...
}

あなたは必要としないvarの前にaaとして関数の実行コンテキストに入り、仮パラメータので、それは既に宣言されています、。
FABRICIOマット

6

var FOO = FOO || {};カバーする2つの主要な部分があります。

#1オーバーライドの防止

コードを複数のファイルに分割していて、同僚がと呼ばれるオブジェクトで作業しているとしFOOます。次に、誰かがすでにFOO機能を定義して機能を割り当てているというケースにつながる可能性がありskateboardます。それがすでに存在するかどうかを確認していなかった場合は、それをオーバーライドします。

問題のあるケース:

// Definition of co-worker "Bart" in "bart.js"
var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker "Homer" in "homer.js"
var FOO = {};

FOO.donut = function() {
  alert('I like donuts!');
};

この場合、Homerが新しいオブジェクトを定義する(したがって、Bartからの既存のオブジェクトをオーバーライドする)ため、HTMLの後にskateboardJavaScriptファイルをロードすると、関数のみが認識され、関数についてのみ認識されます。homer.jsbart.jsFOOdonut

したがって、var FOO = FOO || {};「FOOがFOO(既に存在する場合)または新しい空のオブジェクト(FOOがまだ存在しない場合)に割り当てられることを意味するを使用する必要があります。

解決:

var FOO = FOO || {};

// Definition of co-worker Bart in bart.js
FOO.skateboard = function() {
  alert('I like skateboarding!');
};

// Definition of co-worker Homer in homer.js
var FOO = FOO || {};

FOO.donut = function() {
  alert('I like donuts!');
};

バートとホーマーは、今の有無をチェックしているのでFOO、彼らは彼らのメソッドを定義する前に、あなたは読み込むことができますbart.jsし、homer.js(彼らは別の名前を持っている場合)、互いのメソッドをオーバーライドすることなく、任意の順序インチ したがって、常にFOOメソッドskateboarddonut(Yay!)を持つオブジェクトを取得します。

#2新しいオブジェクトを定義する

最初の例を読んだことがあれば、すでにの目的は何ですか|| {}

既存のFOOオブジェクトがない場合、ORケースがアクティブになり、新しいオブジェクトが作成されるため、それに関数を割り当てることができます。お気に入り:

var FOO = {};

FOO.skateboard = function() {
  alert('I like skateboarding!');
};

3

AEROTWISTに値がないか、nullまたは未定義の場合、新しいAEROTWISTに割り当てられる値は{}(空白のオブジェクト)になります


1

||オペレータは、2つの値をとります。

a || b

aが真実なら、それは戻りaます。それ以外の場合は、が返されbます。

falsy値はnullundefined0""NaNfalse。真実の値は他のすべてです。

そのaため、設定されていない場合(そうである場合undefined)は戻りbます。


真実偽りが実際の言葉として永続化されるべきかどうかはわかりません。面白いですが、厳密には標準的ではありません。:-)
2011年

4
@Orblingは、JSでそのような値について話すために非常に一般的に使用されています。
Alnitak

+1は、論理演算子ではないため、演算子を正しく記述します。「デフォルト演算子」と呼ばれることもあります。
TimBüthe11年

@Tim ||JS(およびPerl)とC、C ++、およびJavaのバージョンの唯一の違いは、JSが結果をブール値にキャストしないことです。それはまだ論理演算子です。
Alnitak

@Alnitak:おそらく、過去のJS開発者の非専門的な背景が原因です。
オーブリング

-1

IEの一部のバージョンでは、このコードは期待どおりに機能しないことに注意してください。のでvar、変数が再定義されると、その割り当てられた-私が正しく問題を思い出した場合-あなたは、常に新しいオブジェクトを持つようになってしまいます。これで問題が解決するはずです:

var AEROTWIST;
AEROTWIST = AEROTWIST || {};
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.