JavaScriptの未宣言・var・let変数の挙動の違いを解説

プログラミング

JavaScriptにおける変数の宣言方法は、constを除くと以下の4つがあります。

・未宣言

var1 = "var1";

のように、値が代入された時点で変数が宣言されたものとみなされる。

・var

var var1;

のように、var句により変数を宣言する。

・var(巻き上げ)

var1 = "var1";
var var1;

のように値が代入された後にvarにより変数が宣言された場合、変数が宣言された後に値が代入されたものとみなされる。
この例では、以下と同価とみなされる。

var var1;
var1 = "var1";

・let

let var1;

のように、var句により変数を宣言する。
ES6のバージョン以降でサポートされている。

これらの宣言方法の違いにより、非Strictモードの場合に以下の挙動の違いが生じます。
(varの巻き上げについては、巻き上げしなかった場合と同じです)

なお、Strictモードの場合は、varやletやconstを用いて宣言をせずに変数に値を代入した場合にReferenceErrorで異常終了するようになります。


以下、挙動を確認するためのサンプルコードです。
(Node.jsで確認します)

それぞれの変数で以下を確認します。

・var1

ブロック外で宣言した変数をブロック内でも宣言。
ブロック内の変更がブロック外に影響するなら、ブロックを出た時点で変数が書き変わる。

・var2

ブロック内でのみ変数を宣言。
ブロック内の変更がブロック外に影響するなら、ブロックを出た時点で参照不可になる。

・var3

関数内でのみ変数を宣言。 関数内の変更が関数外に影響するなら、関数を出た時点で参照不可になる。

【テストコード(未宣言)】

・test.js

var1 = "var1";
console.log("before change  :" + var1);

if (true) {
    var1 = "var1mod"
    var2 = "var2";
    console.log("in block       :" + var2);
}
console.log("after change   :" + var1);
console.log("out of block   :" + var2);

function func() {
    var3 = "var3";
    console.log("in function    :" + var3);
    return var3;
}
func();
console.log("out of function:" + var3);

【実行結果(未宣言)】

c:\tmp>node test.js
before change  :var1
in block       :var2
after change   :var1mod
out of block   :var2
in function    :var3
out of function:var3

c:\tmp>

【テストコード(var)】

・test.js

var var1 = "var1";
console.log("before change  :" + var1);

if (true) {
    var var1 = "var1mod"
    var var2 = "var2";
    console.log("in block       :" + var2);
}
console.log("after change   :" + var1);
console.log("out of block   :" + var2);

function func() {
    var var3 = "var3";
    console.log("in function    :" + var3);
    return var3;
}
func();
// console.log("out of function:" + var3); // ReferenceError

【実行結果(var)】

c:\tmp>node test.js
before change  :var1
in block       :var2
after change   :var1mod
out of block   :var2
in function    :var3

c:\tmp>

【テストコード(var巻き上げ)】

・test.js

var1 = "var1";
var var1;
console.log("before change  :" + var1);

if (true) {
    var1 = "var1mod"
    var var1;
    var2 = "var2";
    var var2;
    console.log("in block       :" + var2);
}
console.log("after change   :" + var1);
console.log("out of block   :" + var2);

function func() {
    var3 = "var3";
    var var3;
    console.log("in function    :" + var3);
    return var3;
}
func();
// console.log("out of function:" + var3); // ReferenceError

【実行結果(var巻き上げ)】

c:\tmp>node test.js
before change  :var1
in block       :var2
after change   :var1mod
out of block   :var2
in function    :var3

c:\tmp>

【テストコード(let)】

・test.js

let var1 = "var1";
console.log("before change  :" + var1);

if (true) {
    let var1 = "var1mod"
    let var2 = "var2";
    console.log("in block       :" + var2);
}
console.log("after change   :" + var1);
// console.log("out of block   :" + var2); // ReferenceError

function func() {
    let var3 = "var3";
    console.log("in function    :" + var3);
    return var3;
}
func();
// console.log("out of function:" + var3); // ReferenceError

【実行結果(let)】

c:\tmp>node test.js
before change  :var1
in block       :var2
after change   :var1
in function    :var3

c:\tmp>

いかがでしたでしょうか。

この記事では、JavaScriptの変数宣言の違いによる挙動の違いをまとめてみました。
色々と書きましたが、現在の実務ではletを使うのが無難です。
letであれば、Javaの変数と同じような感覚で使うことができます。

コメント

タイトルとURLをコピーしました