読者です 読者をやめる 読者になる 読者になる

望月いちろうのREADME.md

書き溜めておいた技術記事や旅行記のバックアップです。

Node.jsでのvar, let, constの違いについて比較してみた

Node.js JavaScript

f:id:mochizuki_p:20161005031521j:plain

JavaScriptの新しい規格ES6では従来の変数宣言varに加えlet,constという2つの新しい宣言形式が使えるようになりました。今回はこの2つの特徴を従来のvar型と同様に比較してみたいと思います。

var

グローバル参照の変数です。実は僕はスコープが有効だと思っていましたが実は違うようです。実際に試してみます

test_var.js

{
   var k = 1;
   console.log(k)
}
console.log(k)

これを実行すると・・・

node test_var.js

結果

0
1
1

えっ・・・!

スコープから外れたのに値が参照できている・・!

これはおかしいじゃないかっ・・!

実際サーバーサイドでJavaScriptを利用するとなるとこの辺りの緩さは大きな問題になります。だからスコープが有効になるような変数が必要になります。そんなわけでletやconstが登場したわけですね〜

letとconstを利用するにはスクリプトの最初の行にuse strictを記述する必要があります。

'use strict';

let

前述した通りでスコープが有効になります。しかし注意しないといけないのはletはあくまで変数であるということです! swiftの経験がある方は間違えてしまうかもしれません。

test_let.js

'use strict';

{
let i = 1;
console.log(i);
}
console.log(i)

let y = 0;
console.log(y);
y = 1;
console.log(y);

実行すると

node test_let.js

結果

1
undefined
0
1

スコープから外れると参照が消えてくれました!また変数の再代入もできていることに注目してください。しつこいですがletは定数ではありません! あと注意すべきなのは再宣言ができないということ。たとえば

'use strict';

let a = 1;
let a = 0;

とするとエラーになります。

const

最後はconstになります。これは定数で一度宣言すると中身を変えることはできません。またletと同様スコープから外れると自動的に消滅する性質があります。

test_const.js

'use strict';

{
const k = 0;
console.log(k)
}
console.log(k)

const l = 0;
l=1;
console.log(i);

実行すると

0
0

letと同様にスコープから外れた時点で参照が消滅していることが確認できます。また代入も無効になっていることが確認できたと思います。

constには落とし穴があり、実はオブジェクトの中身は変更できてしまいます。

const k = {}
k["a"] = "a"
console.log(k) // {"a":"a"}
k = 0 //これは無効

どうしてlet, constを使用すべきなのか?

端的に言えばプログラムが安全になるからです。一般的にグローバル変数を使用することはアンチパターン(避けるべき作法)として知られています。それは作成者の意図しない所で変数を書き換えや誤参照が発生することで、バグを引き起こす原因になるからです。これはプログラムの規模が大きくなるほど発生しやすく、それを避けるには、極力ローカル変数(プログラムの一部からしかアクセスできない)を利用するように心がけることが重要です。let,constを利用するとスコープが外れた時点で変数が削除されるので非常に便利です。

加えてNode.jsでは問題になりがちなメモリーリークの問題もあります。メモリーリークは使用していない変数が蓄積して、新しいメモリの割り当てが不可能になることが原因です。本来はブラウザで利用される前提で設計されたJavaScriptはこの辺りの対策が不完全でした。

しかし、Node.jsの普及と共にサーバーサイドでの利用が増えてくると、メモリーリークが問題になり始めました。これを避けるにはstrictモードを有効にして極力varの利用を避けるべきです。