JavaScript letを使った方がいい事例を観測しました


Twitter上で質問を受けて不思議な挙動のコードに出会いました。ドキュメントとかあんまり読まないのでガバガバな説明ですがどうしても共有したい事例だったので書かせていただきます。ご容赦ください。

スコープを限定しないからダメとよくいわれるvarを使って事故が起きたので、スコープを限定するletを使おうというお話です。(2019/7/18 追記: スコープの問題と言えるものの、当方の認識に誤りがあるかもしれません。現在確認中です)

JavaScript
let elm = document.createElement("div");

var status = ["hoge", "fuga"];

Array.prototype.forEach.call(status, (t)=>{
  elm.innerHTML += t + "<br />";
});

document.body.appendChild(elm);

このコード、あえてvarArray.prototype.forEachを使用しました。

varletにした場合とで挙動が異なっています。

var_status
h
o
g
e
,
f
u
g
a
let_status
hoge
fuga

window.statusはすでに変数として存在している1ため、varでの宣言では再代入となります。その結果暗黙の型変換が行われ、文字列配列が文字列となってしまいます。結果としてこのような想定外の挙動をとったのでした。

つまるところvar statusのほうは次のコードとほぼ等価です。

JavaScript
let status = ["hoge", "fuga"].toString();

varを使うとこんな恐ろしいバグに出くわすのですね。。くわばらくわばら...

まぁ今回の場合、statusを予約語とみなして回避するのがベストとも取れるんですけどね。

とりあえず他のケースでも似たようなことが起きないようにするために、自戒としてやっぱりこれからは積極的にletを使いたいなと思ったのでした。

駄文失礼しました。ここまで読んでくださりありがとうございました。m(_ _)m


  1. 存在意義がよくわからなかったです... window.status - Web API | MDN