JavaScriptでの変数、スコープ、および巻き上げについて理解する

提供:Dev Guides
移動先:案内検索

序章

変数は、多くのプログラミング言語の基本的な部分であり、初心者のコーダーが学ぶ最初の最も重要な概念の1つです。 JavaScriptには変数のさまざまなプロパティがあり、名前を付けるときに従わなければならないいくつかのルールがあります。 JavaScriptでは、変数の宣言に使用される3つのキーワード(varlet、およびconst)があり、それぞれがコードによる変数の解釈方法に影響を与えます。

このチュートリアルでは、変数とは何か、変数を宣言して名前を付ける方法について説明し、varlet、およびconstの違いについても詳しく見ていきます。 また、巻き上げの影響と、変数の動作に対するグローバルスコープとローカルスコープの重要性についても確認します。

変数を理解する

変数は、値を格納するために使用される名前付きコンテナーです。 複数回参照する可能性のある情報は、後で使用または変更するために変数に格納できます。 JavaScriptでは、変数内に含まれる値は、数値、文字列、オブジェクトなど、任意のJavaScriptデータ型にすることができます。

今日のJavaScriptが基づいているECMAScript2015(ES6)言語仕様以前は、変数を宣言する方法はvarキーワードを使用するしかありませんでした。 その結果、ほとんどの古いコードと学習リソースは、変数にvarのみを使用します。 以下の独自のセクションで、varlet、および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キーワードで宣言された定数変数の名前は、通常、すべて大文字で記述されます。

これは学ぶべき多くのルールのように思えるかもしれませんが、有効で従来の変数名を書くことはすぐに第二の性質になります。

varlet、および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ステートメントによっては、x200に変わる可能性がありますが、条件がfalseであったため、[の値に影響を与えることはありませんでした。 X157X]。 代わりに、xhoist()関数の先頭に引き上げられ、値はundefinedになりました。

このタイプの予測できない動作は、プログラムにバグを引き起こす可能性があります。 letconstはブロックスコープであるため、以下に示すように、この方法で吊り上げることはありません。

// 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識別子を大文字で記述するのが一般的な規則です。 これにより、他の変数値と簡単に区別できるようになります。

以下の例では、変数SPECIESconstキーワードを使用して定数として初期化します。 変数を再割り当てしようとすると、エラーが発生します。

// 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キーワードの制限のいくつか、およびletconstがこれらの問題を修正する方法についても学びました。

他の言語での変数の使用方法を比較するには、「 Python3で変数を使用する方法」に関するチュートリアルをお読みください。