2011-08-10 11 views
8

論理ORを使ってオブジェクトを宣言するとき、私は奇妙な動作をします。varキーワードと論理ORを持たない変数を宣言する

my_var = my_var || {}; // throws TypeError 

私は

var my_var = my_var || {}; // returns empty object 

varキーワードを追加する場合は、なぜこれが?私は説明を見つけることができないようです。 my_varはグローバルスコープなので、なぜvarが動作を変更していますか?第二の状況では

+0

もう少しコードを提供できますか? my_varは同じスコープ内のある時点でスクリプトの初期に定義されていますか?私はそう思うだろう。 –

+0

はい、 'my_var'は実行の早い段階で宣言されるべきです。具体的には、別のjavascriptソースです。私はIE8でテスト中にこれに遭遇しました。 FireFoxは期待通りに動作しましたが、IE8では実行時間の問題が発生しました。この謎は、私がデバッグしようとしていたときに浮かび上がった。 –

+0

これは、私が実際に明示的に未定義をチェックする正当な理由のようです。 – Kzqai

答えて

5

最初の例では、my_varと呼ばれる識別子(または空のオブジェクト)から値を読み取ることによってmy_varという名前のグローバルオブジェクトのプロパティに割り当てる試みます。ただし、その時点で識別子my_varは定義されていないため、失敗します。

第2の例では、javacriptの変数ホイストがどのように機能するかによって、my_var変数が割り当てられて読み込まれると、変数が既に宣言されています。

はまた、この例を見て:varキーワードで

a = a; // fails, undeclared identifier 
a = 0; 

それが動作します!

b = b; // succeeds allthough identifier undeclared?! 
var b = 0; 

変数の巻き上げがこの中にそれを向けるだろう。これは次のとおりです。

var b; // declaration of b hoisted to the top of scope 
b = b; 
b = 0; 
0

は、私のVARが定義されていない変数が2番目の例では{}

1

ある空のオブジェクトが割り当てられているので、varmy_varの範囲を定義します。これにより、値を適切に設定することができます。ここでは両方の例で何が起こっているかで、拙速な表情だ:

例1では、JSエンジンは、次の操作を行うことがあります。

  1. my_varが存在するかどうかを確認するために、現在のスコープを確認してください。
  2. my_varが見つかるまで上記のスコープ(およびそのスコープ)を確認します。
  3. が見つからていないときグローバルスコープでmy_varを作成します。*

*あなたがmy_varに値を代入しようとすると、ステップ3がまだ起きていません。

例2:

  1. は、現在のスコープでmy_varという名前の変数がありますか?はい、varというキーワードを使用して作成しました。
  2. その値を割り当てます。
0

私はスペックを引用することはできませんが、私はvar文の初期化は単なる糖衣構文であることを前提としています

var my_var = my_var || {}; 

は、

var my_var; 
my_var = my_var || {}; 
と同等です。

最初の行では、my_varが宣言され、暗黙的に特殊値undefinedに設定されています。次に、2行目でmy_varが存在し、undefinedfalseと評価され、エラーは発生しません。

ただし、右側が評価されるとmy_varは不明なので、エラーです。

+0

しかし、なぜ 'var'は宣言を変更するのですか? 'var'は' my_var'を初期化する独特な関数を持っていますか?あるいはそれを見る別の方法は、なぜ 'var'は論理ORの振る舞いを変えるのでしょうか? –

+0

'var'はORの動作を変更しません! 'var'は* local *変数を宣言し、その変数に' undefined'を代入します。 'var'を指定せずに変数を宣言すると、* global *変数が作成されます。 –

1

varなしで変数を定義すると、global objectに直接アクセスしています。つまり、あなたのJavaScriptエンジンはグローバルオブジェクト上でmy_varを検索しようとします(ブラウザにいる場合はwindow)。そのプロパティはまだ存在しないので、JSエンジンはスローします。

エンジンがmy_varの変数を読み込もうとすると、文のの右側にあるになります。割り当てのように

my_var = {}; 

が動作します。しかし、varのない識別子にアクセスすると、ブラウザはスコープチェーンを検索します。グローバルオブジェクトのvariable objectはグローバルオブジェクトそのものなので、ルックアッププロシージャはどこも終了しません(=例外)。

varキーワードをinfrontにすると、jsエンジンはparsetimeでその識別子名で新しい変数を宣言する必要があることを知ります。実際には、その変数をundefinedという値で宣言しています(これは "ホイスト"と呼ばれます)。つまり、varを使用すると、早急にその名前のcurrent contextにプロパティが作成されます。したがって、そのコードが関数または評価コンテキストに含まれていない場合、windowオブジェクトにはmy_varというプロパティが作成されます。

0

最初の場合、定義されていない変数を割り当てようとします。そのあなたが書くのと同じ:

my_var = a || {}; 

第2のケースでMY_VARを使用すると、varキーワードを使用AN実際の範囲でMY_VARを作成するようにのみ定義されていません。 Undefinedはfalseに変換され、空のオブジェクトが返されます。

0

興味深いことに、この作業します:あなたは「VAR」キーワードを使用する場合

a = my_var || {}; // 'a' is now an empty object 

あなたは文字通りのコマンドを与えている「新しい変数を作成して、この値を割り当てます。」 'var'を使用しない場合は、変数がすでにどこかにグローバルスコープ内に存在していることを意味しています。

この例では、JavaScriptエンジンは 'my_var'の現在の値を検索しようとします。存在しないと判断し、現在値を割り当てようとしているため作成できません。

関連する問題