JavaScriptの変数、スコープ、およびホイストの理解

前書き

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

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

変数を理解する

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

今日のJavaScriptが基づいているECMAScript 2015 (ES6)言語仕様の前は、変数を宣言する唯一の方法がありました—varキーワードを使用することです。 その結果、ほとんどの古いコードと学習リソースは、変数にvarのみを使用します。 以下のits own sectionで、varlet、およびconstキーワードの違いについて説明します。

varを使用して、変数自体の概念を示すことができます。 以下の例では、変数をdeclareし、それに値をassignします。

// 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ではidentifiersとして知られています。 ここに要約されている、Understanding Syntax and Code Structure in JavaScriptで識別子に名前を付ける規則のいくつかについて説明しました。

  • 変数名は、文字(a-z)、数字(0-9)、ドル記号($)、およびアンダースコア(_)のみで構成できます。

  • 変数名に空白文字(タブまたはスペース)を含めることはできません

  • 数字で変数の名前を始めることはできません

  • 変数の名前として使用できないreserved keywordsがいくつかあります

  • 変数名では大文字と小文字が区別されます

JavaScriptには、varまたはletで宣言された関数および変数の名前にキャメルケース(キャメルケースとして定型化されることもあります)を使用する規則もあります。 これは、最初の単語を小文字で書き、その後にスペースのない後続のすべての単語の最初の文字を大文字にする習慣です。 いくつかの例外を除き、定数ではないほとんどの変数はこの規則に従います。 constキーワードで宣言された定数変数の名前は、通常、すべて大文字で記述されます。

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

varlet、およびconstの違い

JavaScriptには、変数を宣言するための3つの異なるキーワードがあり、言語に複雑さの層を追加します。 3つの違いは、スコープ、巻き上げ、および再割り当てに基づいています。

キーワード 範囲 巻き上げ 再割り当て可能 再宣言できます

var

関数スコープ

Yes

Yes

Yes

let

ブロックスコープ

No

Yes

No

const

ブロックスコープ

No

No

No

あなたは自分のプログラムで3つのうちどれを使うべきか疑問に思うかもしれません。 一般的に受け入れられている方法は、可能な限りconstを使用し、ループや再割り当ての場合はletを使用することです。 一般に、varは、レガシーコードでの作業以外では回避できます。

可変スコープ

JavaScriptのScopeは、JavaScriptへの変数のアクセス可能性を決定するコードの現在のコンテキストを指します。 スコープの2つのタイプは、localglobalです。

  • Global variablesは、ブロック外で宣言されたものです

  • Local variablesは、ブロック内で宣言されたものです

以下の例では、グローバル変数を作成します。

// 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キーワードで宣言された変数は常に関数スコープです。つまり、関数は別個のスコープを持つものとして認識されます。 したがって、このローカルスコープの変数は、グローバルスコープからアクセスできません。

ただし、新しいキーワードletconstblock-scopedです。 これは、ファンクションブロック、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までの変数を使用しており、initializedには値があります。 宣言して初期化した後、変数にアクセスまたは再割り当てできます。

宣言および初期化される前に変数を使用しようとすると、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を変数としてメモリに保存しました。 定義される前にまだ呼び出されていたため、結果は100ではなくundefinedになります。 ただし、ReferenceErrorが発生してスクリプトが停止することはありません。 varキーワードは実際にはvarの場所を変更しませんでしたが、これは巻き上げがどのように機能するかを表すのに役立ちます。 ただし、このコードを作成したプログラマーは、undefinedではなくxの出力がtrueであることを期待しているため、この動作によって問題が発生する可能性があります。

次の例では、巻き上げが予測不可能な結果を​​もたらす可能性があることも確認できます。

// 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であるため、xの値に影響を与えることはありません。 代わりに、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のメカニズムであるホイストの影響を受ける可能性があります。 これにより、コードに未定義の変数が生じる場合があります。 letconstの導入により、変数を宣言する前に変数を使用しようとしたり、変数を複数回宣言しようとしたりすると、エラーがスローされるため、この問題が解決されます。

定数

多くのプログラミング言語はconstantsを備えています。これは、変更または変更できない値です。 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がこれらの問題を修正する方法についても学びました。

変数が他の言語でどのように使用されるかを比較するには、「https://www.digitalocean.com/community/tutorials/how-to-use-variables-in-python-3 [変数の使用方法Python 3]。」