調べてみました
ES2015(ES6)javascriptの変数宣言で使うconst, let, varについて今更調べてみました。
それぞれの違いは以下で分類できます。
- 再代入
- 再定義
- スコープ
- ホイスティング(巻き上げ)
それぞれについてどんなものか見ていきましょう。
再代入
- var, letで可。
- constでは不可。
var a = 1;
let b = 1;
a = 10;
b = 100;
console.log(a);
console.log(b);
10
100
const a = 1;
a = 10;
console.log(a);
Uncaught TypeError: Assignment to constant variable.
再定義
- varのみ可。
- let, constでは不可。
var a = 1;
var a = 100;
console.log(a);
100
!?再代入なんて出来ちゃうんだ・・・エラーにしてくれないと絶対ソース分かりづらくなりそう・・・
let a = 1;
let a = 100;
console.log(a);
Uncaught SyntaxError: Identifier 'a' has already been declared
こっちが普通だよね・・・
const a = 1;
const a = 100;
console.log(a);
Uncaught SyntaxError: Identifier 'a' has already been declared
スコープ
- varは関数。
- let, constはブロック(
{・・・}
)。
if (true) {
var aisatsu = "Hello!";
console.log(aisatsu);
}
console.log(aisatsu);
Hello!
Hello!
ifの中で宣言したのにその下でも使える・・・!?
``` js:let,constはブロック({・・・}
)
if (true) {
let aisatsu = "Hello!";
console.log(aisatsu);
}
console.log(aisatsu);
> Hello!
> Uncaught ReferenceError: aisatsu is not defined
こっちの方がわかりやすいなぁ・・・
<br>
## ホイスティング(巻き上げ)
- varはされる。
- let, constはされない。
``` js:varはされる
console.log(aisatsu);
var aisatsu = "Hello!";
undefined
console.log(aisatsu);
let aisatsu = "Hello!";
Uncaught ReferenceError: Cannot access 'aisatsu' before initialization
ちなみにホイスティングについて補足・・・
以下のソースは、aisatsuという変数を宣言、初期化する前に呼んでいますが、ReferenceError
にはなっていません。
変数の宣言が関数の一番上に「巻き上げ」られています。
console.log(aisatsu);
var aisatsu = "Hello!";
内部ではこのソースのように動いている、ということですね。
var aisatsu;
console.log(aisatsu);
aisatsu = "Hello!";
こんな問題(?)があるので、jsでは(let,constが出てくるまでは)変数の宣言は関数の最初にやろうねという思想が生まれています。他のプログラミング言語を知ってても知らなくてもあまり直感的ではなさそうです・・・。
結論
varはあまり直感的でないので、むやみに使用するとどこかでバグらせそう。また、letやconstは他の言語での変数と同様に動いてくれそうなので、こちらを使用した方が良さそうです。
変数定義はほとんどconstで良さそう。const使いまくろうっと。
数え上げする変数とかはlet。varはもう使わない。以上!