2012-01-30 9 views
7
だけで知的好奇心のうち

、なぜJavaScriptを(zは最初に定義され得るような)は、zを初期化するためにJavascript:z = z || [] VARを使用しないときにエラーを投げます - なぜですか?

var z = z || []; 

を受け入れない

が、VARせずに、それは(グローバル空間に)

z = z || []; 
を、エラーがスローされます

(zが未定義の場合)

グローバル空間では、VARを使用する必要はありませんが、b e悪い習慣。

あなたは、これが

What is the purpose of the var keyword and when to use it (or omit it)?

があることの宣言のような質問の重複であると言う前に、「あなたはグローバルスコープにいる場合は、その後に違いありません。」

明らかに、私の実際の例を考えれば、それは100%真実ではありません。

これは奇抜なことですか、正当な論理ですか?私はそれを学んだとの回答の概要を追加


:ティムへ

感謝を(下記参照)私の誤解の鍵は、(ジャバスクリプトの基本的な)

これを実現していませんでした

var z;既に存在する場合は何もありません。

「var z」が常に初期化されると仮定すると、この式は両方向になるように見えます。

「var z」は、zが定義されていることを単純に確認しますが、既存の値には実際には影響しません。それから、もしzが既に存在するならば、それが使われていれば、変数はただ宣言されていますが、空になりますので使用されませんが、エラーはスローされません。

これはJavaScriptで問題をスコープと巻き上げのこの種の逸品です。 http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting

minitechとあまりにも貢献した皆に感謝します!

+2

一般的なルールとして、実際のエラーメッセージをコピーすることは、通常、単に「エラーをスローする」よりも役に立ちます。 –

答えて

6

z = z || []は、スコープチェーン内にzが存在しない範囲(グローバルかどうか)にスローされます。これは、式が最初に右側のzという既存の変数の値を取得しようとするため、存在しない場合はエラーになります。 (まだ存在していない場合)

var z = z || []がエラーをスローしない理由は、式が実行される前に、効果は一般的にを巻き上げとして知られている変数zが作成されていることです。

一方、未解決の識別子(たとえばz = 2)に値を代入すると、スコープ内でエラーなしで動作します(ECMAScript 5の厳密なモードでは、それとスローを禁止します)。識別子を解決できない場合は、グローバルオブジェクトであるスコープチェーン内の最終オブジェクトのプロパティとして追加され、グローバル変数を作成するように見えます。

+0

ああ、私はそれを得ると思います。だから "var z"は "create a new z"のように左側で最初に行われますが、右側では "old z"を探します。その順番で、 "z"はちょうど左側で初期化されているので、右側の "z"は空ですが、未定義ではありません。 varがなければ、右の "z"は空ではなく、未定義です。えええええええええええええええええええええええええええん - 「var z」が左に新しいものとして定義している場合、このコードはどのように既存の値を保持していますそれは両方の方法があるように思えます、右のために左に初期化するだけでなく、右の値を保持することができます。 –

+0

@ck_:はい、私はあなたがそれを持っていると思いますが、 'undefined'はJavaScriptの実際の値であり、実際には変数に割り当てられたデフォルト値です(例えば、' var x; ')。 'undefined 'の初期値を持つ' x'という変数を生成します。これは宣言されていない 'x'とは区別されます)。私は "宣言されていない"または "存在しない"のために行くだろう。 –

+0

@ck_:既存の値を保持することに関して、 'var z;'は、その値が何であれ、 'z'が既に存在するならば、全く何もしません。 –

10

効果は正しいです。 varは、常にその "オペランド"を宣言しますが、宣言していないときは、スクリプトは未定義の変数を使用しようとし、エラーをスローします。

グローバルスコープの場合は、存在しない変数に割り当てることができます。その変数は宣言するのと同じ効果があります。もちろん、あなたの場合、それは未定義です。これは、それが知的好奇心からかもしれないが、それはそうしても意味がありませんので、あなたが

var z = z || []; 

を書かないだろう、言われています。むしろ、次のようにすることができます。

if(!window.z) { 
    window.z = []; 
} 

実際、グローバルスコープ(決して;)ではない)で宣言するとき、私はより明確にするためにwindow.somethingを代わりに使用します。

+0

**宣言していないと、スクリプトは未定義の変数を使用しようとします** - あなたがz = zにアクセスすると言っているのを待っていますが、var z = zはアクセスしていませんか? 2番目のzはまだグローバルスコープにあり、関数の外にある場合は1番目です。 (困惑) –

+1

@ck_:違いは、 'var'を使うと' z'変数が作成されてから文が実行されることです。 –

4

宣言されていない変数z = 123に割り当てることができます。しかし、あなたはz = z || []が行うものを読むことを試みることはできません。

関連する問題