ということで、配列の中身をシャッフルする関数で分割代入構文を使ったのだが「Cannot set property 'hoge' of undefined」や、定義したはずの変数が「'hoge' is not defined」というエラーがでてしまった。
いろいろ調べたので結果をまとめる。
問題のコード
const values = [1,2,3,4,5,6,7,8,9,10]
let i = values.length
while(i--) {
const r = Math.floor(Math.random() * i)
[values[i], values[r]] = [values[r], values[i]]
}
console.log(...values)
このコードを実行すると、分割代入構文のところで「'r' is not defined」というエラーがでる。
分割代入構文の直前に「console.log(r)」を入れると、ちゃんと変数rは定義されている。それなのに正常に動作しない。
デバッグしようと、分割代入構文の直前に「debugger」を入れると正常に動作した。
謎い。。。
配列をシャッフルするコード書いたんだけど、debuggerをコメントアウトすると動かない。debugger書くとちょっと遅延するのかな?ってかMath.floor、Math.randomって非同期だっけ? https://t.co/Po3yNCTcSH— ダーシノ (@bc_rikko) 2017年1月29日
どうやら分割代入([values[i], values[r]] = [values[r], values[i]])してるところがダメっぽい。temp使って入れ替えたら動いたから。しかし、なんでダメなんだろ?— ダーシノ (@bc_rikko) 2017年1月29日
問題を単純化してみる
前述のコードだとうまくいかなかったので、もっと単純化してみる。
var a = 1
var b = 2
console.log(a,b)
[a, b] = [b, a]
console.log(a,b)
このコードを実行すると「Uncaught TypeError Cannot set property '2' of undefined」というエラーがでる。これもまた分割代入構文の直前に「debugger」を入れてみたところ正常に動作した。
謎い。。。
MDNのサンプルどおり書いてみる
単純化してもダメだったので、MDNに載っている「変数の入れ替え」のサンプルコードをそのまま実行してみる。
var a = 1;
var b = 3;
[a, b] = [b, a];
console.log(a, b);
正常に動作した?!
「問題を単純化してみる」で書いたコードとMDNのサンプルを比較したところ、違いは「セミコロンの有無」だけ。
ということで、前述の2つのコードにセミコロンを追加したところ...正常に動作した?!?!
どうやら分割代入の[](ブラケット記号)が直前の処理の続きとして解釈されていたらしい。debuggerは制御系のステートメントなので、他の処理部とは明確にわけられるので、独立した処理と解釈されエラーにならなかった。
ようやく原因がわかった!直前のコードにセミコロンがないと分割代入するときにエラーになるらしい。で、debuggerを入れればその行は処理部とは明確にわかれるからエラーにならないんだ!— ダーシノ (@bc_rikko) 2017年1月29日
vue-cliでLintにStandardを選ぶとセミコロンがあると怒られてしまう。また最近Pythonの勉強を再開したので、「セミコロン」=「省くべきもの」だと錯覚していたため、今回の問題にぶちあたってしまった。
普通にJavaScriptを書くときは、セミコロンを付けましょー!
参考サイト
以上
written by @bc_rikko
0 件のコメント :
コメントを投稿