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);