while で条件を満たす間くり返す
このレッスンで分かること
while (条件) { }は、条件が真である間くり返します- 条件に使う値をループの中で変えないと、永久に止まりません
何周で終わるかが、始める前に分からない
for は「配列の要素数だけ」「10 回」のように、回数が先に決まっている処理のための道具でした。ですが、始めてみないと終わりが分からない処理もあります。累計が目標に届くまで、目当てのものが見つかるまで、条件を満たすまで。回数ではなく状態でくり返しを止めたいときに使うのが while です。
JavaScript
let remaining = 3;
while (remaining > 0) {
console.log("公開まであと " + remaining + " 日");
remaining--;
}
// 公開まであと 3 日
// 公開まであと 2 日
// 公開まであと 1 日丸カッコの条件を見て、真なら中を実行し、また条件に戻る。偽になったら抜ける。それだけです。for はカッコの中に初期化と更新がまとまっていましたが、while は初期化をループの前に、更新をループの中に、自分で置くことになります。そのぶん書き忘れても文法エラーにならない、というのが while の難しさです。
条件がひとつだと、配列の外まで見に行く
配列を while でまわすときは、条件がひとつでは足りません。目当てのものが最後まで見つからなかった場合、インデックスが要素数を超えても回り続けます。範囲外の要素は undefined なので、そのまま計算に混ぜれば結果は静かに壊れます。
そこで && で条件を 2 つつなぎ、「まだ範囲内で、かつ、まだ見つかっていない間」とします。
JavaScript
const statuses = ["下書き", "下書き", "公開"];
let i = 0;
while (i < statuses.length && statuses[i] !== "公開") {
i++;
}
console.log(i); // 2範囲の検査を左に書くのが大事です。&& は左が偽なら右を見ないので、範囲を超えた瞬間に右の statuses[i] は評価されません。
条件が 2 つあるということは、ループを抜けた理由も 2 つあるということです。見つかって抜けたのか、要素が尽きて抜けたのか。抜けた直後に if でどちらだったかを確かめる、というのが while の定番の作法です。
JavaScript
if (i === statuses.length) {
console.log("公開済みの作品はまだありません");
}更新を書き忘れると、二度と返ってこない
while でいちばん怖いのが無限ループです。条件に使っている値がループの中で変わらなければ、条件は永遠に真のままです。
JavaScript
let day = 0;
while (day < 3) {
console.log(day);
// day++ が無いので止まらない
}文法としては完全に正しいので、エラーも警告も出ません。while を書いたら「条件に出てくる変数はどれか」「それはループの中で変わるか」の 2 つを必ず確かめてください。とくに day++ を if の中に書くと、更新されない周ができて止まらなくなります。更新は if の外、本体のいちばん最後に置くのが安全です。
よくある間違い
- 条件の向きを逆にする — 書くのは「くり返したい条件」であって「終わりたい条件」ではありません。
0から増えていく変数にwhile (total > 100)と書くと、1 周も実行されずに終わります - 初期化をループの中に置く — 本体の先頭に
let day = 0;と書くと毎周ゼロに戻り、条件がいつまでも偽になりません。初期化はwhileの前です
要件
- 関数名は
daysToGoal、引数は数値の配列dailyViewsと数値goalの 2 つ、戻り値は数値 - くり返しには
while文を使うこと - 配列の範囲を超えないよう、条件を
&&で 2 つ組み合わせること - 目標に届かなかった場合は
-1を返すこと
入出力例
daysToGoal([], 100) → -1
daysToGoal([120], 100) → 1
daysToGoal([30,40,50], 100) → 3
daysToGoal([10,20], 100) → -1
daysToGoal([50,50], 100) → 2