format_list_bulleted
【JavaScript】変数や定数・スコープについて解説
最終更新日時:2020-05-13 15:06:34



JavaScriptに限らずプログラミングを扱う際には変数や定数を用いることが多いでしょう。さらに、変数や定数にはスコープという考え方があり、関数やif文内部でのみ変数・定数が使える仕組みがあります。本記事では変数や定数の基本的な使い方とスコープについて解説します。

変数を宣言する

変数とは値を入れるための箱にあたるものです。スクリプトによる処理によってデータの内容を変更していく際に変数を用いることによってデータをスクリプト内の異なる箇所に移動させたりすることができます。変数は宣言することで変数の名前をJavaScriptに認識させメモリを確保することができます。本項では変数の宣言と利用方法について解説します。

letで変数を宣言する

let 変数名 = 初期値

letを用いることで上のように変数を宣言することができます。変数には=によって初期値が代入されます。=は代入演算子と呼ばれる演算子です。letで宣言した変数には次のような特徴があります。

  • 初期値を代入する必要がある
  • 初期値が代入された際に初期化
  • 変数の重複ができない
  • ブロックスコープが適用される
  • 変数の巻き上げが起こらない

letでは変数宣言時に初期値を必ず代入する必要があります。また、一度宣言した変数と同じ名前の変数を宣言することはできません。

let hoge = "ホゲホゲ"
let hoge = "ふがふが" //エラーが発生する

letを使用した場合はif文やfor文などにおいて、{}を用いたブロックスコープを用いることができます。ブロックスコープの説明については2.3項を参照にしてください。さらに、初期値が代入された際に初期化されるため変数の巻き上げが起こらないのも大きな特徴です。変数の巻き上げについては2.2項を参照してください。これらか紹介するvarに比べて用いやすい宣言方法であるため、変数の宣言にはletを用いることが推奨されています。

varで変数を宣言する

var 変数名 [= 初期値]

varを用いることで上のように変数を宣言することができます。再代入が可能であるため基本的な変数としての性質はletと変わりませんが、次のような特徴を持ちます。

  • 初期値を省略しても良い(宣言だけできる)
  • 変数の再宣言ができる
  • ブロックスコープが適用されない
  • varを省略した場合でも宣言できる
  • 変数の巻き上げが起こる

varを用いた場合、変数の初期値を省略することができます。

var 変数名

宣言時には変数にはundefinedと呼ばれるデータが入っています。また、varで宣言した場合はletでできない変数の再宣言をすることができます。

let hoge = "ホゲホゲ"
let hoge = "ふがふが" 

一方で、変数宣言前もundefinedを格納している変数として利用できるため関数の利用時に変数の巻き上げ問題が起きてしまう場合があるので注意が必要です。変数の巻き上げ(hoising)とはローカルスコープ内で変数が宣言された際に、グローバル変数を宣言前に用いてしまうと変数が未定義(undefined)となってしまうことです。varを省略して宣言した変数の宣言と代入を行った場合、varで宣言した場合と同じ変数とし扱われます。ただし、変数宣言と代入をした場所に限らず、グローバルスコープの変数として扱われるため注意が必要です。

letとvarの違い

letとvarの違いを表にまとめると次のようになります。

種類再宣言再代入初期値関数スコープブロックスコープ
var可能可能
なくても良い適用される適用されない
let不可能可能
必ず必要適用される
適用される

変数のスコープの使い方

スコープとは変数を使える範囲のことです。スコープを設定することで変数の値を操作できる箇所を制限することができ、これにより変数の値が予期せぬ箇所で変更されてしまうリスクを制限するなどのメリットがあります。JavaScriptのスコープには関数スコープとブロックスコープがあり、letとvarの仕様の違いが大きく影響する内容でもあります。本項ではスコープについて説明します。

  • グローバルスコープ
  • ローカルスコープ
    • 関数スコープ
    • ブロックスコープ 

関数スコープの使い方

原則的に関数内で宣言する変数はローカル変数と呼び、関数スコープが適用されます。一方で関数の外で宣言された変数はグローバル変数と呼ばれグローバルスコープが適用されます。しかし例外的にvarを省略して宣言された値に関してはグローバルスコープが適用されます。

let hoge = "ほげ"
function func() {
    console.log(hoge)
}
func() //"ほげ"

上のように、グローバルスコープで宣言された変数はローカルスコープ内で用いることができます。varで宣言した場合も同じです。

function func() {
    let hoge = "ほげ"
}
func()
console.log(hoge) //ReferenceError: hoge is not defined(エラー)

上のようにローカルスコープで宣言した変数はスコープ外では使用できません。varで宣言した場合も同じです。

function func() {
    hoge = "ほげ"
}
func()
console.log(hoge) //"ほげ"

上のようにvar宣言の際にvarを省略するとグローバル変数として扱われるため、関数スコープ外でも変数を使用することができます。

変数の巻き上げについて(hoisting)

前項で説明したようにvarで宣言した変数は初期値が代入される以前でもundefinedの値が格納された状態で用いることができます。

var hoge = "ホゲ"
function func() {
    console.log(hoge) //undefined
    var hoge = "ほげ"
    console.log(hoge) //ほげ
}
func()

関数内では関数スコープが適用されるため、関数内でhogeを定義する前に関数内でhogeを出力すると未定義状態として扱われます。このような振る舞いのことを変数の巻き上げ(hoising)と言います。関数の外でhogeを出力するとグローバルスコープで宣言されているホゲが使用されます。なお、letを使用した場合は変数の宣言と初期値を代入する前に変数を使用するとエラーが出るため巻き上げは起こりません。

ブロックスコープの使い方

ブロックスコープとは{}で囲まれた部分内のスコープです。if文やswitch文などが挙げられます。ブロックスコープの使い方は関数スコープの使い方と同じですが重要な点が一つだけあります。それは、ブロックスコープはletで宣言した変数にのみ適用されることです。varで宣言された変数には適用されません。

let hoge = "ホゲ"
{
    let hoge = "ほげ"
    console.log(hoge); //"ほげ"
}
console.log(hoge); //"ホゲ"

グローバルスコープとブロックスコープでそれぞれ異なる変数が宣言されています。

var hoge = "ホゲ"
{
    var hoge = "ほげ"
    console.log(hoge); //"ほげ"
}
console.log(hoge); //"ほげ"

varで宣言された変数にはブロックスコープは適用されないため、ブロック内で宣言された変数もグローバルスコープとして扱われています。

constで定数を宣言する

const hoge = "ほげ"

定数とは再代入ができない変数のことです。また、再宣言もできません。constは次のような特徴を持ちます。

  • 再宣言ができない
  • 宣言する際に初期値を代入しなければならない
  • 再代入ができない
  • 関数スコープが適用される
  • ブロックスコープ が適用される

データ型について

代表的なデータ型

JavaScriptは文字列を扱うString型や数字を扱うnumber型、真偽値を扱うBoolean型などが用意されていますが、これらはプリミティブ型と呼ばれる基本的な型です。JavaScriptは動的な型付言語であるため、String型が代入されている変数にNumber型の値を入れることができます。しかし、コードの読みやすさなどの観点からは変数の型を変えすぎるのは良くないため、注意しましょう!

プリミティブ型の種類は次のようになっています。

データ型取り扱うデータ
String型文字列
Number型数値
Boolean型真偽値
null型null値(存在していない値)
undefined型未定義状態である値
Symbol型不変のデータ
Bigint型大きな数値

これらのプリミティブ型以外にObject型(参照型)の変数・定数もあります。これらについて学習したい方は「JavaScriptでのarray(配列)の書き方・使い方について解説」「JavaScriptでの連想配列(オブジェクトリテラル)の書き方・使い方について解説」を参照してみましょう!

ラッパーオブジェクトを活用する

プリミティブ型のデータはラッパーオブジェクトのメソッドを用いることができます。例えばString型の値はStringオブジェクトのメソッドを継承しているため扱うことができます。

hoge = "ほげ"
hoge.Stringオブジェクトのメソッド

同様のことがNumber型でもBoolean型などでも使うことができます。String型について詳しく知りたい方は「JavaScriptの文字列操作について解説」を参照してみましょう!

この記事のまとめ

本記事ではJavaScriptでの変数・定数とスコープの扱いを、具体例を元に説明しました!最後に記事の要点をまとめてみましょう。

  • 変数はletとvarを用いて宣言することができる。
  • 特別な理由がない限りletで宣言する方が良い。
  • スコープには関数スコープとブロックスコープがある。
  • 定数はconstを用いて宣言することができる。
  • プリミティブ値にはいくつかの方があり色々な種類のデータを扱うことができる。
  • プリミティブ値のデータにはラッパーオブジェクトがあり、ラッパーオブジェクトのメソッドを用いることができる。

JavaScriptを是非活用してみましょう!