いまさら聞けないJavaScript変数について
駆け出しエンジニア
普段、なんとなくJavaScriptでvar宣言して変数をつかっているけど、実は体系的に知らなかったりする。一度、体系的に学習しなおしたい。

上記の問いに回答します。

この記事を書いているぼくは、現在プログラミングスクールで学習中ですが、プログラミングは大学時代から触っていまして、かれこれ10年ほど経過します。

プログラミングは「使い方」を知っていればなんとなくできてしまう部分がありますが、早期エラー解決や設計するのであれば、しっかり知識を体系化しておくとスムーズにエラー解決や設計する事ができます。

という事で、今回はJavaScriptの変数について解説していきます。

変数には3つの種類があります

以下の通りです。

  • var
  • let
  • const

順に解説していきます

”var”キーワードについて

"var"キーワードは 値の再代入が可能な変数を宣言します。

以下の通りです。

var var_name = "変数宣言1回目";
console.log(var_name);
// var_name => 変数宣言1回目
var var_name = "変数宣言2回目";
console.log(var_name);
// var_name => 変数宣言2回目

ポイント :"var"キーワードはスコープは持っていない

例えば以下の通りです。

var var_name = "var 変数宣言 1回目";
console.log(var_name);
// var_name => "var 変数宣言 1回目"
function myFunc(){
 var var_name = "var 変数宣言 2回目";
 console.log(var_name);
 // var_name => "var 変数宣言2回目"
}
myFunc();
//myFunc呼び出し

"let"キーワードについて

"let"キーワードは値の再代入が可能ですが、同一スコープ内で同じ変数名で再定義できない宣言です。

例えば以下の通りです。

let let_name = "let 変数宣言 1回目";
console.log(let_name);
// let_name => "let 変数宣言 1回目"
let_name = "let 変数宣言 2回目";
console.log(let_name);
// let_name => "let 変数宣言 2回目"

上記の通り、再代入は可能です。

でも、再定義は不可です。

let let_name = "let 変数宣言 1回目";
console.log(let_name);
// let_name => "let 変数宣言 1回目"
let let_name;
console.log(let_name);
// let_name => "SyntaxError: Identifier 'let_name' has already been declared"

同じ変数名で宣言しようとすると"SyntaxError"となりました。

ポイント :"let"キーワードはブロックスコープを持っている

"let"で宣言された変数にアクセスできるのはブロック内側という事です。逆にいうとブロック毎でスコープは独立しているという事になります。

例えば以下の通りです。

let let_name = "let 変数宣言 1回目";
console.log(let_name);
// let_name => "let 変数宣言 1回目"
function myFunc(){
  let let_name = "let 変数宣言 2回目";
  console.log(let_name);
  // let_name => "let 変数宣言 2回目"
}
myFunc();

上記の通りでして、 グローバル変数として宣言しているlet_name変数(1行目)と、myFunc()内のブロックで宣言している"let_name"変数(7行目)は別スコープとして別の変数として扱われます。

ただし、最初に記載したように同一スコープ内では再定義ができません。

let let_name = "let 変数宣言 1回目";
console.log(let_name);
// name => "let 変数宣言 1回目"
function myFunc(let_name){
  let let_name = "let 変数宣言 2回目";
  console.log(let_name);
  // let_name => "Uncaught SyntaxError: Identifier 'let_name' has already been declared"
}
myFunc(let_name);

上記の通り、"myFunc"の引数に"let_name"を宣言する事で"myFunc"内が同一スコープとして扱われ"SyntaxError"になりました。

"const"キーワードについて

"const"キーワードは、再代入、再定義ができない変数宣言です。

以下の通り、再代入は不可です。

const const_name = "const 変数宣言 1回目";
console.log(const_name);
const_name = "const 変数宣言 2回目";
// name "Uncaught TypeError: Assignment to constant variable."
console.log(const_name);

以下の通り、再定義も不可です。

const const_name = "const 変数宣言 1回目";
console.log(const_name);
// const_name => "const 変数宣言 1回目"
const const_name;
console.log(const_name);
// const_name => "Uncaught SyntaxError: Identifier 'const_name' has already been declared"

よく定数として使用される"const"キーワードですが、これは初期値から変更できない特性をもつ変数宣言のためです。

ブロックスコープについて

上記の"let"キーワードにて少し触れましたが、"let"と"const"はブロックスコープを持ちます。

以下の通りです。

var x = 0;
let y = 0;
const z = 0;
console.log(x); 
// var => 0
console.log(y); 
// let => 0
console.log(z); 
// const => 0
if(true){
    var x = 1;
    let y = 1;
    const z = 1;
    console.log(x); 
    // var => 1
    console.log(y); 
    // let => 1
    console.log(z); 
    // const => 1
    };
console.log(x); 
// var   => 1
console.log(y); 
// let   => 0
console.log(z); 
// const => 0

注目して頂きたいのは、23行目~28行名のconsole.log結果です。

"let"と"const"キーワードは"0"になっています。これはif文がブロックスコープとして扱われているためです。

変数の巻き上げについて

変数の巻き上げは、スコープ内で宣言された変数が宣言された場所に関係なく、スコープの先頭で宣言されることです。

例えば、以下の通りです。

console.log(var_name);
// name => "undefined"
var var_name = "var 変数宣言 1回目";

"var_name"は"SyntaxError"ではなく"undefined"になります。

ポイント:"var"と"let"と"const"では巻き上げに違いあり

以下の通りです。

console.log(var_name);
// var_name => "undefined"
var var_name = "var 変数宣言 1回目";
console.log(let_name);
// name => "Uncaught ReferenceError: Cannot access 'let_name' before initialization"
let let_name = "let 変数宣言 1回目";
console.log(const_name);
// name => "Uncaught ReferenceError: Cannot access 'const_name' before initialization"
const const_name = "const 変数宣言 1回目";

"var"キーワードだけ変数の巻き上げがされます。一方、"let"と"const"キーワードは変数の巻き上げはされません。

まとめ:ブロックスコープと巻き上げ

"var"、"let"、"const"キーワードはまとめると以下の通りです。

再代入
再定義ブロックスコープ変数巻き上げ
"var"×
"let"××
"const"× × ×

ややこしいですね。

今回は以上です。

関連記事