MENU

Loading...

ES2015の新機能を学ぶ〜letとconstの特徴とvarとの使い分け

これまで変数宣言はvarのみでしたが、ES2015ではletconstという宣言方法が加わりました。
この2つの宣言方法は以下のような特徴があります。

  1. ブロックスコープを持つ
  2. 再宣言が出来ない
  3. 変数の宣言前の参照はエラーとなる

特徴を一つずつ見ていきたいと思います。

ブロックスコープを持つ

スコープとは、変数が参照可能な範囲のことで、varでは関数単位でのスコープのみでした。しかし、letconstでは、関数単位でのスコープに加え、ブロック単位でスコープを生成します。

まずは以下のサンプルコードから。

(function() {
  'use strict';

  if (a) {
    var b = 10;
  }
  console.log(b);

  if (a) {
    let c = 10;
  }
  console.log(c);

  if (a) {
    const d = 10;
  }
  console.log(d);
}());

// => 10
// => エラー
// => エラー

varの場合、if内で宣言しても外から参照出来てしまいます。これはJavaScriptをメインに書いている人にとってはごく普通の挙動でした。
しかし、letconstはif内で宣言した場合、その外からは参照が出来ない、つまりブロックスコープが生成されていることを意味します。

再宣言が出来ない

letconstは、strictモード下での再宣言をエラーにします。varでは再宣言が出来ていました。

(function() {
  'use strict'
 
  var a = 10;
  var a = 11; // varは再宣言できる
 
  console.log(a);
}());

// => 11

letconstでは、下記の通り再宣言はエラーとなります。

(function() {
  'use strict'
 
  let a = 10;
  let a = 11; // エラーを返す

  const b = 10;
  const a = 11; // エラーを返す
}());

変数の宣言前の参照はエラーとなる

これまでのJavaScriptで唯一の変数宣言であったvarは巻き上げという仕様を持っていました。

変数の巻き上げって?

JavaScriptには変数の巻き上げという少しやっかいな仕様があります。これは変数をどこで宣言しても、その関数や文の先頭で宣言したものとされるというものです。説明だけだとわかりずらいので、サンプルコードを見てみます。

var shinnosuke = 'abe';

(function() {
  console.log(shinnosuke);
  var shinnosuke = 'ogasawara';
  console.log(shinnosuke);
}());

// => undefined
// => ogasawara

上記のサンプルコードでは最初のconsole.logで期待する結果はabeだと思います。しかし、ここで変数の巻き上げという仕様が働きます。変数の巻き上げとは、関数内で宣言した変数はどこで宣言しても関数の先頭で宣言されたものとされるのでした。そしてこの場合、代入位置はそのままで変数だけを宣言している状態となる為、結果がundefinedとなるのです。

つまり、上記のサンプルコードは、わかりやすくすると下記のように書き換えることが出来ます。

var shinnosuke = 'abe';

(function() {
  var shinnosuke;
  console.log(shinnosuke);
  shinnosuke = 'ogasawara';
  console.log(shinnosuke);
}());

// => undefined
// => ogasawara

変数の宣言を全て関数や文の先頭で行なっているコードを目にしたことがあって「あれ?」と思った方もいると思いますが、それはこの巻き上げという仕様が影響しています。

letとconstの違いって?

ここまでletconstの共通の特徴を書いてきましたが、続いてこの2つの違いです。それは再代入が可能か否かです。letは再代入が可で、constは再代入が不可です。また、constは再代入は不可ですが、オブジェクトの書き換えは可能である点は注意です。

const Carp = {
  a: 'Tanaka',
  b: 'Kikuchi',
 c: 'Maru'
};
 
Carp.a = 'Soyogi';
 
console.log(Carp);

// => Object {a: "Soyogi", b: "Kikuchi", c: "Maru"}

まとめ

ES2015時代の変数宣言はletconstを使いましょう。とりわけvarを使う場面は今のところ思い当たりません。

更に言うと、実は再代入する場面というのはそれほど多くないです。したがって必然的にconstを仕様する場面が多くなると思います。基本的にはconstを使用し、再代入が必要な場合のみletを使いましょう。