変数の宣言と変数の初期化の違いを知りたいです。例えば.
var example; // this is declaring
var example = "hi" // initializing? Or just "adding a value"?
私はそこにいるとは思いませんが、それぞれの定義は正確には何ですか?それとも基本的に同じ意味ですか?
編集:@ThisClarkはコメントで何かを言った、そして私は彼が間違っていることを証明するために行った、そしてスペックをもう少し読んだときに私は何かを学んだ:
仕様 以外の情報は次のとおりです。
var
ステートメントは、実行中の実行コンテキストのVariableEnvironmentにスコープされる変数を宣言します。 Var変数は、それらを含むLexical Environmentがインスタンス化されるときに作成され、作成時にundefined
に初期化されます。 [...] Initializerを使用してVariableDeclarationで定義された変数には、変数の作成時ではなく、VariableDeclarationの実行時にInitializerのAssignmentExpressionの値が割り当てられます。
私がこれを読んだことに基づいて、次の点は、あなたが質問で尋ねた振る舞い(および用語の「正しい」使用法)を説明しています。
A 変数宣言(例:var foo
)は、「字句環境」がインスタンス化されるとすぐに、その変数をcreatedにします。たとえば、その変数が関数本体内で定義されている場合、その関数は「字句環境」であるため、変数の作成は関数自体のインスタンス化と一致します。
明らかに、変数宣言は初期化子(つまり、変数の初期値に解決される右辺の式)で作成される場合とされない場合があります。これは「初期値」という用語のかなり非仕様的な使用法ですが...もう少し掘り下げてみましょう。
技術的に、ここでの仕様書によると、すべての変数は値undefined
で初期化されます。
変数が作成され[...]、未定義に初期化されます
initializerも提供された場合、これは主に学術的なものであるため、そこでは「技術的に」強調します。
すでに説明したことに基づいて、ステートメントvar foo;
が存在する可能性がありますanywhere関数本体内で、同じ関数内の他の場所に移動しても、関数自体の実行時セマンティクスには影響しません(実際の割り当てやその他の参照があるかどうかに関係なくto foo
が発生します)。それでも混乱する場合は、前のポイントを読み直してください。
動作の最後の部分は最も直感的な部分であり、それはinitializerのassignmentです。この割り当ては、そのコード行が実際にexecutedであるときに行われます(これも、変数が技術的に取得された時点と同じではありませんcreated)。
したがって、簡単に要約すると、次のようになります。
var
を使用)は常に字句環境の初期化時にundefined
で初期化されます。それがお役に立てば幸いです(そして私が仕様をひどく誤解しなかったことを!)。
@ jmar777の答えは、間違いなく仕様の最良の説明と内訳です。ただし、実践的な学習者にとっては、少し説明的なコードが役立つことがわかりました。 ;)
基本的な考え方
window.varName = value
と入力するのと同じです)。undefined
のassignment(コードの最初の行ですぐに別の値が割り当てられた場合でも)。したがって、初期化は私たちにとって重要な用語ではありません。宣言して割り当て、Javascriptエンジンを初期化します。
だからあなたの質問の例に直接答えるには:
var example;
は変数を宣言し、初期化中にundefined
の値が割り当てられます。var example = "hi"
は変数を宣言し、最初はundefined
の値も割り当てられますが、実行中に実際にそのコード行に到達すると、文字列「hi」に再割り当てされます。
例示的なコード
function testVariableDeclaration() {
// This behaves 'as expected'....
console.log(test2, 'no value assigned yet'); // --> undefined 'no value assigned yet'
// ....but shouldn't our actual expectation instead be that it'll throw an error since
// it doesn't exist yet? See the final console.log() below!
// As we all know....
test1 = 'global var'; // ....a variable assignment WITHOUT declaration in the current
// scope creates a global. (It's IMPLICITLY declared.)
// But a little counter-intuitively....
test2 = 'not global'; // Although this variable also appears to be assigned without
// declaration like 'test1', the declaration for 'test2' that
// appears *later* in the code gets hoisted so that it's already
// been declared in-scope prior to this assignment.
console.log( test1, window.test1 === test1 ); // --> 'global var' TRUE
console.log( test2, window.test2 === test2 ); // --> 'not global' FALSE
var test2; // As shown by the above console.log() outputs, this variable is scoped.
console.log( test3 ); // Throws a ReferenceError since 'test3' is not declared
// anywhere, as opposed to the first console.log() for 'test2'.
}
宣言/割り当てに対する「スコープ」の影響
宣言と代入の違いをさらに明確にするのは、declaring変数が常に現在のスコープ内に新しい変数を作成することです(myVar
- (scopeB)、同じ名前の変数が親スコープにすでに存在している場合でも(myVar
scopeA)。次に、新しい値をmyVar
に割り当てすることができますscopeB現在のスコープ内の任意の時点で、再宣言する必要はありません。 (この割り当ては、myVar
の値には影響しません。scopeA。)の終わりにscopeBに到達、myVar
scopeBは割り当てに使用できなくなります。
反対に、特定のスコープ内の変数に、そのスコープ内で宣言せずに値を割り当てると、次のスコープに割り当てられます。 -「スコープチェーン」の最上位宣言(または、上位の宣言が見つからない場合、グローバルは暗黙的に宣言されます)。
したがって、変数はスコープごとに1回宣言する必要があります。各宣言は親スコープで行われた宣言をオーバーライドします(つまり、個別の変数を作成します)。ただし、スコープに固有であることが意図されている場合は、スコープ内で宣言する必要があります。代入は必要に応じて何度でも行うことができますが、最も「厳密に宣言された」変数にのみ影響します(より適切な用語がないため)。
唯一の違いは、var
ステートメントが値なしで宣言された変数をundefined
に初期化する
どちらの例でも、変数を宣言しています。
var
ステートメントなしで変数に値を割り当てると、スコープチェーンを下って宣言された変数を探し、最終的にグローバルwindow
オブジェクトにフォールバックします。
宣言とは、基本的に、プログラムに新しいエンティティを導入することを意味します。初期化とは、変数に最初の値を与えることです。したがって、基本的に上記の例は正しいです。
ここに欠けている小さなことがあります。概念を理解するためのアナロジーはこのようなものです。変数ごとに、何らかの値を割り当てる必要があります。
すべての変数のデフォルト値(明示的に言及されていない場合は未定義)
1) let example; // this is declaring and initializing with undefined
2) example="hi"; // this is assigning the value to hi
3) let example = "hi" // this is declaring and initializing with "hi"
したがって、3番目のステートメントは実質的に1 +2と同じです。
さて、ステートメント3が可能であるのに、なぜステートメント1が必要なのかという疑問が生じるかもしれません。
その理由は、変数の範囲を拡大するためです。
例えば行番号8に変数が必要であるとしましょう。しかし、値は遅くまで利用できず、それもコードブロックで利用できます。
1) {
2) let a;
3) try{
4) a=someFunctionWhichMayThroeException();
5) }
6) catch(e){
7) a=100;
8) }
9) someFunctionOnA(a);// the variable is required here
10)
11) }
上記の変数を宣言することにより、変数のスコープが拡大され、tryブロックの外部で使用できるようになりました。
PS:これは使い方のほんの一例です。
宣言とは、プログラムに新しい名前を導入することです。
var test; // Is this a declaration ?
初期化とは、値の「割り当て」を指します。
var test = {first:"number_one"} // Now that object is initialized with value