宣言されていない変数を読み取ることはできません。それが_gaq || []
、最後のケースの式で試みていることです。
この場合
_gaq = _gaq || [];
_qaq
以前に宣言されておらず、右側 ( _gaq || []
) が評価されると、エラーがスローされます。
この場合に何が起こっているかを順を追って説明します。
代入演算子は、仕様のセクション 11.13.1で説明されています。
生産性AssignmentExpression : LeftHandSideExpression = AssignmentExpression
は次のように評価されます。
1.lref
を評価の結果とするLeftHandSideExpression
。
2.rref
を評価の結果とするAssignmentExpression
。
...
LeftHandSideExpression
は_gaq
、AssignmentExpression
は_gqa || []
。
そのため、変数が宣言されていないため、最初_qaq
に評価され、解決できない参照が発生します。_gaq
この評価はエラーをスローしません。
その後_gqa || []
、評価されます。これは であり、セクション 11.11で としてLogicalORExpression
説明されています。この場合、は左側で、 はで、右側は です。
式は次のように評価されます。LogicalORExpression || LogicalANDExpression
LogicalORExpression
_gaq
LogicalANDExpression
[]
1.lref
を評価の結果とするLogicalORExpression
。
2. ましょlval
うGetValue(lref)
。
...
は宣言されていないlref
ため、解決できない参照になることは既にわかっています。_gaq
それでは、何をしているのか見てみましょう(セクション 8.7.1でGetValue
定義されています。は に渡される値です):V
GetValue
1. そうType(V)
でない場合はReference
、 を返しV
ます。
2.base
を呼び出した結果としGetBase(V)
ます。
3. の場合IsUnresolvableReference(V)
、ReferenceError
例外をスローします。
...
ご覧のとおりReferenceError
、このプロシージャの 3 番目のステップでエラーがスローされ、代入の右辺を評価することによって実行されます。ここでエラーがスローされます。
では、なぜこれが起こらないのvar _gaq = _gaq || [];
ですか?
この行:
var _gaq = _gaq || [];
実際には
var _gaq;
_gaq = _gaq || [];
巻き上げと呼ばれるもののため[MDN] . つまり、_gaq
が評価されると、解決できない参照にはならず、値を持つ参照になります。undefined
(変数_gaq
が既に宣言されている (そして潜在的に値を持っている) 場合、var _gaq
効果はありません。)
_gaq
関数内からグローバルに作成する場合は、次を参照して明示的window
に行います。
window._gaq = window._gaq || [];