JavaScript本格入門(ISBN 978-4774184111)で基礎からJavaScriptを勉強するシリーズです。
今回はChapter2から変数と定数についてです。
変数
変数宣言
変数宣言はvar命令で行います。
var 変数名; // 変数宣言
var 変数名 = 初期値; // 変数宣言と初期化
リテラルの型によって変数のデータ型が自動的に変わります。
データ型が自動的に変わる例を下記に示します。
var x = 1; // 変数xを数値型リテラルで初期化
console.log(typeof x); // 出力:number
x = 'Hello world!'; // 変数xに文字列型リテラルを代入
console.log(typeof x); // 出力:string
変数xは数値を代入したときは数値型になり、文字列を代入したときは文字列型になっていることが分かります。JavaScriptには型がないというのは誤解です。
※typeof演算子はオペランドの型を文字列で返してくれます。
変数宣言(ES2015)
ES2015からはletによる変数宣言が標準化されました。構文はvar命令と同様です。
ES2015が使える環境ではvarよりもletを使うようにしたほうが良いです。
コンパイル時にvarよりもletの方が厳密なチェックが行われ安全です。
let 変数名; // 変数宣言
let 変数名 = 初期値; // 変数宣言と初期化
varとの違いを順番に見ていきます。
変数の重複がNG
let x = 'hoge';
let x = 'foo';
let x = 'foo';
^
SyntaxError: Identifier 'x' has already been declared // 同名の変数がすでに宣言されている!!!
at new Script (vm.js:79:7)
at createScript (vm.js:251:10)
at Object.runInThisContext (vm.js:303:10)
at Module._compile (internal/modules/cjs/loader.js:657:28)
at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10)
at Module.load (internal/modules/cjs/loader.js:599:32)
at tryModuleLoad (internal/modules/cjs/loader.js:538:12)
at Function.Module._load (internal/modules/cjs/loader.js:530:3)
at Function.Module.runMain (internal/modules/cjs/loader.js:742:12)
at startup (internal/bootstrap/node.js:283:19)
同様のことをvarで行った場合エラーとならず、後から宣言された変数がxを上書きしてしまいます。
letを使うことでソースコードが長い場合にうっかり変数を上書きしてしまうなどの事態を防げます。
ブロックスコープに対応している
let x = 1;
if (x === 1) {
let x = 2;
console.log(x); // 2を出力
}
console.log(x); // 1を出力
2
1
これはifブロック内で宣言した変数xと、外で宣言した変数xが別のものであることを意味しています。
JavaScriptでない言語を学んだ人からするとごく自然なことです。
一方、これをvarを使うと下記のようになります。
var x = 1;
if (x === 1) {
var x = 2;
console.log(x); // 2を出力...?
}
console.log(x); // 1を出力...?
2
2
varはブロックスコープに対応していません。したがってifブロック外で先に宣言された変数xをifブロック内で宣言された変数xで上書きしてしまいました。
それがvarの仕様と言ってしまえばおしまいなのですが、直感的にはおかしな動きなので、letを使う方がミスが防げそうです。
定数
定数宣言
const命令を使用します。ES2015から標準化されました。
値を変えられたくない固定値は定数を利用します。
const X = 3.14;
X = 3.15; // 値を変えようとしてみる
X = 3.15;
^
TypeError: Assignment to constant variable. // ちゃんと怒られました
注意点
参照型を定数にする場合アドレス自体は変更不可ですが、参照先のデータは定数とならないので注意が必要です。
const GIORNO_GIOVANNA = {stand: 'Gold Experience'};
try {
GIORNO_GIOVANNA = 'change!'; // 参照型の定数自体は変更できないッ!
}catch(error){ // TypeError: Assignment to constant variable.
console.log('Unless! Unless! Unless!');
}
GIORNO_GIOVANNA.stand = 'Gold Experience Requiem'; // 参照先のデータは変更可能なので注意ッ!
console.log(GIORNO_GIOVANNA);