0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

JavaScriptの変数: ホイスティングとスコープの理解

Posted at

JavaScriptの変数を効果的に使うには、ホイスティングやスコープの仕組みを正確に理解することが大切です。このブログでは、JavaScriptの変数宣言に関わる重要な概念を整理します。

1. ホイスティング(Hoisting)とは?

ホイスティングは、JavaScriptエンジンがコードを実行する前に変数や関数をメモリ上に「持ち上げる」動作を指します。この仕組みにより、コード内で変数や関数を宣言位置より前に参照することが可能になります。

2. 関数スコープとブロックスコープ

JavaScriptには主に2つのスコープ(変数の有効範囲)があります:

関数スコープ(Function Scope)

  • 関数内で宣言された変数は、その関数の外ではアクセスできません。
  • varで宣言された変数は関数スコープを持ちます。
function test() {
  var x = 10;
  console.log(x); // 10
}

console.log(x); // ReferenceError: x is not defined

ブロックスコープ(Block Scope)

  • ブロック({})内でのみ有効であり、外からアクセスすることはできません。
  • letとconstはブロックスコープを持ちます。
{
  let y = 20;
  const z = 30;
  console.log(y, z); // 20, 30
}
console.log(y); // ReferenceError: y is not defined

3. 変数のライフサイクル

変数のライフサイクルは、変数が宣言されてから使用可能になり、最終的にメモリから解放されるまでの一連の過程を指します。varletconstではこのライフサイクルに明確な違いがあります。それぞれの挙動をホイスティングとスコープの観点から詳しく説明します。

varのライフサイクル

  • 有効範囲:
    varは関数スコープを持ちます。そのため、関数内で宣言された変数は関数外からアクセスできません。

  • ホイスティング:
    varは宣言と初期化が同時にホイスティングされ、初期値はundefinedになります。そのため、宣言位置に関係なくコード内で使用可能です。

  • メモリ管理:
    関数が終了すると変数はメモリから解放されます。

:

function example() {
  console.log(x); // undefined
  var x = 10; // 宣言と初期化
  console.log(x); // 10
}
example();
console.log(x); // ReferenceError: x is not defined

letのライフサイクル

  • 有効範囲:
    letはブロックスコープを持ちます。ブロック({})内でのみ有効であり、ブロックが終了するとメモリから解放されます。

  • ホイスティング:
    letは宣言のみがホイスティングされます。ただし、初期化が完了するまではTDZ(Temporal Dead Zone)内にあり、アクセスするとエラーが発生します。宣言後に初期化されていない場合、undefinedが自動的に割り当てられます。

  • メモリ管理:
    ブロックが終了するタイミングで変数はメモリから解放されます。

:

{
  console.log(y); // ReferenceError: Cannot access 'y' before initialization
  let y = 20;
  console.log(y); // 20
}
console.log(y); // ReferenceError

constのライフサイクル

constletと同様にブロックスコープを持ちます。

  • ホイスティング:
    宣言のみがホイスティングされますが、初期化が完了するまではTDZ内に置かれます。ただし、constは宣言と初期化が同時に行われる必要があるため、実質的にTDZが存在しないような動作になります。

  • 値の不変性:
    初期化後、値を変更することはできません。ただし、これは変数が保持しているメモリの参照先が変更できないことを意味します。オブジェクトのプロパティや配列の要素は、その参照先を通じて自由に変更可能です。

  • メモリ管理:
    ブロック終了時にメモリから解放されます。

:

{
  const z = 30;
  console.log(z); // 30
  z = 40; // TypeError: Assignment to constant variable.
}
console.log(z); // ReferenceError

追加的な注意点

  1. TDZの影響:
    letconstでは、ホイスティングされても初期化される前のアクセスはできません。これにより、未定義の変数を誤って使用することを防ぎます。

    console.log(a); // ReferenceError
    let a = 10;
    console.log(a); // 10
    
  2. 再宣言の挙動:
    varは同じスコープ内で再宣言が可能ですが、letconstでは再宣言は許可されません。

    var x = 1;
    var x = 2; // 問題なし
    
    let y = 1;
    let y = 2; // SyntaxError: Identifier 'y' has already been declared
    
  3. ガベージコレクション:
    変数がスコープ外になると、JavaScriptエンジンのガベージコレクターによってメモリが自動的に解放されます。これは、変数が参照されなくなった場合にガベージコレクターがそのメモリ領域を特定し、解放するプロセスです。この仕組みにより、不要なメモリが解放され、メモリリークを防ぐことができます。

まとめ

JavaScriptの変数宣言方法(varletconst)には、それぞれ独自の特徴と用途があります。ホイスティングやTDZ、スコープの違いを正しく理解することで、予測可能で安全なコードを書くことができます。また、他言語(例: Java)と比較することで、JavaScript特有の動作を深く理解し、適切に活用するスキルを身につけましょう。

0
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?