JavaScriptでの変数、スコープ、および巻き上げについて理解する
序章
変数は、多くのプログラミング言語の基本的な部分であり、初心者のコーダーが学ぶ最初の最も重要な概念の1つです。 JavaScriptには変数のさまざまなプロパティがあり、名前を付けるときに従わなければならないいくつかのルールがあります。 JavaScriptでは、変数の宣言に使用される3つのキーワード(var
、let
、およびconst
)があり、それぞれがコードによる変数の解釈方法に影響を与えます。
このチュートリアルでは、変数とは何か、変数を宣言して名前を付ける方法について説明し、var
、let
、およびconst
の違いについても詳しく見ていきます。 また、巻き上げの影響と、変数の動作に対するグローバルスコープとローカルスコープの重要性についても確認します。
変数を理解する
変数は、値を格納するために使用される名前付きコンテナーです。 複数回参照する可能性のある情報は、後で使用または変更するために変数に格納できます。 JavaScriptでは、変数内に含まれる値は、数値、文字列、オブジェクトなど、任意のJavaScriptデータ型にすることができます。
今日のJavaScriptが基づいているECMAScript2015(ES6)言語仕様以前は、変数を宣言する方法はvar
キーワードを使用するしかありませんでした。 その結果、ほとんどの古いコードと学習リソースは、変数にvar
のみを使用します。 以下の独自のセクションで、var
、let
、およびconst
キーワードの違いについて説明します。
var
を使用して、変数自体の概念を示すことができます。 以下の例では、変数を宣言し、それに値を割り当てします。
// Assign the string value Sammy to the username identifier var username = "sammy_shark";
このステートメントは、いくつかの部分で構成されています。
var
キーワードを使用した変数の宣言- 変数名(または識別子)、
username
=
構文で表される代入演算- 割り当てられている値、
"sammy_shark"
これで、コードでusername
を使用できます。 JavaScriptは、username
が文字列値sammy_shark
を表すことを記憶します。
// Check if variable is equal to value if (username === "sammy_shark") { console.log(true); }
Outputtrue
前述のように、変数は任意のJavaScriptデータ型を表すために使用できます。 この例では、文字列、数値、オブジェクト、ブール値、およびnull値を使用して変数を宣言します。
// Assignment of various variables var name = "Sammy"; var spartans = 300; var kingdoms = [ "mammals", "birds", "fish" ]; var poem = { roses: "red", violets: "blue" }; var success = true; var nothing = null;
console.log
を使用すると、特定の変数に含まれている値を確認できます。
// Send spartans variable to the console console.log(spartans);
Output300
変数はデータをメモリに保存し、後でアクセスして変更することができます。 変数を再割り当てして、新しい値を指定することもできます。 以下の簡単な例は、パスワードを変数に保存してから更新する方法を示しています。
// Assign value to password variable var password = "hunter2"; // Reassign variable value with a new value password = "hunter3"; console.log(password);
Output'hunter3'
実際のプログラムでは、パスワードはデータベースに安全に保存される可能性があります。 ただし、この例は、変数の値を更新する必要がある状況を示しています。 password
の値はhunter2
でしたが、JavaScriptがそれ以降に認識する値であるhunter3
に再割り当てしました。
変数の命名
変数名は、JavaScriptでは識別子と呼ばれます。 JavaScriptの構文とコード構造の理解で識別子の命名規則のいくつかについて説明しました。ここに要約します:
- 変数名は、文字(
a-z
)、数字(0-9
)、ドル記号($
)、およびアンダースコア(_
)のみで構成できます。 - 変数名に空白文字(タブまたはスペース)を含めることはできません
- 数字で変数の名前を始めることはできません
- 変数名として使用できない予約キーワードがいくつかあります
- 変数名では大文字と小文字が区別されます
JavaScriptには、var
またはlet
で宣言された関数および変数の名前にキャメルケース(キャメルケースとして定型化されることもあります)を使用する規則もあります。 これは、最初の単語を小文字で記述し、その後のすべての単語の最初の文字をスペースなしで大文字にする方法です。 定数ではないほとんどの変数は、いくつかの例外を除いて、この規則に従います。 const
キーワードで宣言された定数変数の名前は、通常、すべて大文字で記述されます。
これは学ぶべき多くのルールのように思えるかもしれませんが、有効で従来の変数名を書くことはすぐに第二の性質になります。
var
、let
、およびconst
の違い
JavaScriptには、変数を宣言するための3つの異なるキーワードがあり、言語に複雑さの層を追加します。 3つの違いは、スコープ、巻き上げ、および再割り当てに基づいています。
キーワード | 範囲 | 巻き上げ | 再割り当て可能 | 再宣言できます |
---|---|---|---|---|
var
|
機能範囲 | はい | はい | はい |
let
|
ブロックスコープ | いいえ | はい | いいえ |
const
|
ブロックスコープ | いいえ | いいえ | いいえ |
自分のプログラムで3つのうちどれを使うべきか疑問に思うかもしれません。 一般的に受け入れられている方法は、可能な限りconst
を使用し、ループや再割り当ての場合はlet
を使用することです。 一般に、var
は、レガシーコードでの作業以外では回避できます。
可変スコープ
JavaScriptのScopeは、JavaScriptへの変数のアクセス可能性を決定するコードの現在のコンテキストを指します。 スコープには、ローカルとグローバルの2種類があります。
- グローバル変数は、ブロック外で宣言されたものです
- ローカル変数は、ブロック内で宣言された変数です
以下の例では、グローバル変数を作成します。
// Initialize a global variable var creature = "wolf";
変数を再割り当てできることを学びました。 ローカルスコープを使用すると、元の値を変更または再割り当てすることなく、外部スコープの変数と同じ名前の新しい変数を実際に作成できます。
以下の例では、グローバルspecies
変数を作成します。 関数内には、同じ名前のローカル変数があります。 それらをコンソールに送信することで、スコープによって変数の値がどのように異なり、元の値が変更されていないかを確認できます。
// Initialize a global variable var species = "human"; function transform() { // Initialize a local, function-scoped variable var species = "werewolf"; console.log(species); } // Log the global and local variable console.log(species); transform(); console.log(species);
Outputhuman werewolf human
この例では、ローカル変数はfunction-scopedです。 var
キーワードで宣言された変数は、常に関数スコープです。つまり、関数は別のスコープを持つものとして認識されます。 したがって、このローカルスコープの変数には、グローバルスコープからアクセスできません。
ただし、新しいキーワードlet
およびconst
は、ブロックスコープです。 これは、関数ブロック、if
ステートメント、for
およびwhile
ループなど、あらゆる種類のブロックから新しいローカルスコープが作成されることを意味します。
関数スコープ変数とブロックスコープ変数の違いを説明するために、let
を使用してif
ブロックに新しい変数を割り当てます。
var fullMoon = true; // Initialize a global variable let species = "human"; if (fullMoon) { // Initialize a block-scoped variable let species = "werewolf"; console.log(`It is a full moon. Lupin is currently a ${species}.`); } console.log(`It is not a full moon. Lupin is currently a ${species}.`);
OutputIt is a full moon. Lupin is currently a werewolf. It is not a full moon. Lupin is currently a human.
この例では、species
変数には、グローバルに1つの値(human
)があり、ローカルに別の値(werewolf
)があります。 ただし、var
を使用すると、結果が異なります。
// Use var to initialize a variable var species = "human"; if (fullMoon) { // Attempt to create a new variable in a block var species = "werewolf"; console.log(`It is a full moon. Lupin is currently a ${species}.`); } console.log(`It is not a full moon. Lupin is currently a ${species}.`);
OutputIt is a full moon. Lupin is currently a werewolf. It is not a full moon. Lupin is currently a werewolf.
この例の結果では、グローバル変数とブロックスコープ変数の両方が同じ値werewolf
になります。 これは、var
を使用して新しいローカル変数を作成する代わりに、同じスコープで同じ変数を再割り当てしているためです。 var
は、if
が別の新しいスコープの一部であることを認識しません。 ブロックスコープの変数は、意図せずに変数値をオーバーライドする可能性が低いコードを生成するため、一般的に宣言することをお勧めします。
巻き上げ
これまでのほとんどの例では、var
からdeclare 変数を使用し、初期化値を使用しています。 宣言して初期化した後、変数にアクセスまたは再割り当てできます。
宣言および初期化される前に変数を使用しようとすると、undefined
が返されます。
// Attempt to use a variable before declaring it console.log(x); // Variable assignment var x = 100;
Outputundefined
ただし、var
キーワードを省略すると、変数を宣言するのではなく、初期化するだけです。 ReferenceError
を返し、スクリプトの実行を停止します。
// Attempt to use a variable before declaring it console.log(x); // Variable assignment without var x = 100;
OutputReferenceError: x is not defined
この理由は、 hoisting が原因です。これは、変数と関数の宣言がスコープの最上位に移動されるJavaScriptの動作です。 初期化ではなく実際の宣言のみが引き上げられるため、最初の例の値はundefined
を返します。
この概念をより明確に示すために、以下は私たちが書いたコードとJavaScriptが実際にそれをどのように解釈したかを示しています。
// The code we wrote console.log(x); var x = 100; // How JavaScript interpreted it var x; console.log(x); x = 100;
JavaScriptは、スクリプトの実行前にx
を変数としてメモリに保存しました。 定義される前にまだ呼び出されていたため、結果はundefined
であり、100
ではありません。 ただし、ReferenceError
が発生してスクリプトが停止することはありません。 var
キーワードは、実際にはvar
の場所を変更しませんでしたが、これは巻き上げがどのように機能するかを表すのに役立ちます。 ただし、このコードを作成したプログラマーは、100
の出力を期待しているため、この動作によって問題が発生する可能性があります。
次の例では、巻き上げによって予測できない結果が生じる可能性があることもわかります。
// Initialize x in the global scope var x = 100; function hoist() { // A condition that should not affect the outcome of the code if (false) { var x = 200; } console.log(x); } hoist();
Outputundefined
この例では、x
をグローバルに100
と宣言しました。 if
ステートメントによっては、x
が200
に変わる可能性がありますが、条件がfalse
であったため、[の値に影響を与えることはありませんでした。 X157X]。 代わりに、x
がhoist()
関数の先頭に引き上げられ、値はundefined
になりました。
このタイプの予測できない動作は、プログラムにバグを引き起こす可能性があります。 let
とconst
はブロックスコープであるため、以下に示すように、この方法で吊り上げることはありません。
// Initialize x in the global scope let x = true; function hoist() { // Initialize x in the function scope if (3 === 4) { let x = false; } console.log(x); } hoist();
Outputtrue
var
で可能な変数の重複宣言は、let
およびconst
でエラーをスローします。
// Attempt to overwrite a variable declared with var var x = 1; var x = 2; console.log(x);
Output2
// Attempt to overwrite a variable declared with let let y = 1; let y = 2; console.log(y);
OutputUncaught SyntaxError: Identifier 'y' has already been declared
要約すると、var
で導入された変数は、変数宣言がメモリに保存されるJavaScriptのメカニズムであるホイストの影響を受ける可能性があります。 これにより、コードに未定義の変数が生じる可能性があります。 let
およびconst
の導入により、変数を宣言する前に変数を使用しようとしたり、変数を複数回宣言しようとしたりするとエラーがスローされるため、この問題が解決されます。
定数
多くのプログラミング言語は、定数を備えています。これは、変更または変更できない値です。 JavaScriptでは、const
識別子は定数をモデルにしており、const
に割り当てられた値を再割り当てすることはできません。
すべてのconst
識別子を大文字で記述するのが一般的な規則です。 これにより、他の変数値と簡単に区別できるようになります。
以下の例では、変数SPECIES
をconst
キーワードを使用して定数として初期化します。 変数を再割り当てしようとすると、エラーが発生します。
// Assign value to const const SPECIES = "human"; // Attempt to reassign value SPECIES = "werewolf"; console.log(SPECIES);
OutputUncaught TypeError: Assignment to constant variable.
const
の値は再割り当てできないため、宣言と初期化を同時に行う必要があります。そうしないと、エラーが発生します。
// Declare but do not initialize a const const TODO; console.log(TODO);
OutputUncaught SyntaxError: Missing initializer in const declaration
プログラミングで変更できない値はimmutableと呼ばれ、変更できる値はmutableです。 const
の値は再割り当てできませんが、const
で宣言されたオブジェクトのプロパティを変更できるため、変更可能です。
// Create a CAR object with two properties const CAR = { color: "blue", price: 15000 } // Modify a property of CAR CAR.price = 20000; console.log(CAR);
Output{ color: 'blue', price: 20000 }
定数は、将来の自分自身やプロジェクトで作業している他のプログラマーに、目的の変数を再割り当てしてはならないことを明確にするのに役立ちます。 将来変数が変更される可能性がある場合は、代わりにlet
を使用して変数を宣言することをお勧めします。
結論
このチュートリアルでは、変数とは何か、変数の命名規則、および変数値を再割り当てする方法について説明しました。 また、スコープと巻き上げ、元のvar
キーワードの制限のいくつか、およびlet
とconst
がこれらの問題を修正する方法についても学びました。
他の言語での変数の使用方法を比較するには、「 Python3で変数を使用する方法」に関するチュートリアルをお読みください。