💊

学び直しJavaScript : 変数

2021/12/08に公開

Why

JavaScriptを業務で使うようになり、なんとなーくかけるようになってきた今日このごろ。
ところが、一歩踏み込んだ言語に対する理解が全くできていないということに気づき、改めて深ぼってみようと思います。

const / let / var の違い

const

再代入できない変数の宣言を行う。そのため初期化を同時に行う必要がある。

const hoge = 'abc';

hoge = 'def'; // => TypeError

let

値の再代入が可能な変数の宣言を行う。

let hoge = 'abc';

hoge = 'def'; // => ok

var

値の再代入が可能な変数の宣言を行う。

var hoge = 'abc';

hoge = 'def'; // => ok

だいたいletと一緒(なように思えるが...)

const と let & var の違い

constと他ふたつのキーワードの違いは、再代入できないという点で明確にわかりやすい。
ただし、constで代入した値がプリミティブな値でない場合(配列やオブジェクトなど)、値を変更することができる。

const obj = {
  hoge: 'HOGE'
};

obj.fuga = 'fuga'; // ok

obj = "文字列"; // Uncaught TypeError: Assignment to constant variable.

配列やオブジェクトの中身の変更に関しては問題ないが、objそのものを別のものにしようとするとエラーになる。定数ではなく、あくまで再代入できない変数である。

let(const) と var の違い

本日のメインテーマ。変数の巻き上げを含み、改めて挙動を確認する。

同一スコープ内で何度も同じ変数名で宣言できる

// varの場合
var x = 1;
var x = 2; // 何も言われない
console.log(x); // => 2

// letの場合
let y = 1;
let y = 2; // すでに定義済みのためSyntaxErrorになる。

スコープの違い

// 関数内で宣言した変数はvarもletも関数の外では参照できない
function fn () {
  var x = 1;
  let y = 2;
  const z = 3;
}
console.log(x); // xを参照できない
console.log(y); // yを参照できない
console.log(z); // zを参照できない

// ブロック内で宣言した変数はvarの場合、ブロックの外から参照できる
{
  var x = 1;
  let y = 2;
  const z = 3;
}
console.log(x); // => 1
console.log(y); // yを参照できない
console.log(z); // zを参照できない

変数の巻き上げ

変数の巻き上げとは、varによる変数宣言をした際に、宣言部分が勝手に一番近い関数またはグローバルスコープの先頭に巻き上げられ、代入部分はそのままの位置に残るという特殊な動作のこと

console.log(x); // => undefined
var x = 1;
console.log(y); // => ReferenceError
let y = 2;

これは内部的に以下のような解釈がされている

var x;
console.log(x);
x = 1;

変数の隠蔽

内側のスコープで外側のスコープと同じ名前の変数を定義することで、外側の変数が参照できなくなること。

let x = 'hoge';
{
  let x = 'fuga'
  console.log(x); // => fuga
}
console.log(x); // => hoge

ついついやりがちだがグローバルスコープへ変数をむやみに定義しない(反省)

最後に

日々の業務で感じたり、他の方の記事を読んで注意したいぽいんとをまとめておきます。

  • 変数はできる限り使わない
  • 使うときはスコープを最小にする
  • 基本的にはconstを使い、どうしても再代入が必要な場合だけletを使う

補足、間違い等あればコメントいただけると嬉しいです。

Discussion