while
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since July 2015.
while
文は、テスト条件が真と評価されている間、指定された文を実行するループを作成します。条件はその文を実行する前に評価されます。
試してみましょう
構文
例
while の使用
次の while
ループは、 n
が 3 より小さい間反復します。
let n = 0;
let x = 0;
while (n < 3) {
n++;
x += n;
}
それぞれの反復で、ループは n
を増加させ、それを x
に加えます。したがって、 x
および n
は次の値をとります。
- 最初の通過の後:
n
= 1 およびx
= 1 - 2 回目の通過の後:
n
= 2 およびx
= 3 - 3 回目の通過の後:
n
= 3 およびx
= 6
3 回目の通過が完了した後、条件 n
< 3 は真ではなくなり、ループは終了します。
代入を条件として使用
場合によっては、代入を条件として使用することに意味があることもあります。これは読みやすさとトレードオフの関係にあるので、このパターンを誰にでもわかりやすくするための、ある種の文体上の推奨事項があります。
次の例は、文書のコメントを反復処理し、コンソールにログ出力するものです。
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
let currentNode;
while (currentNode = iterator.nextNode()) {
console.log(currentNode.textContent.trim());
}
これは完全によい例とは言えません。特に次の行があるからです。
while (currentNode = iterator.nextNode()) {
その行の動作は、毎回コメントノードが得られるという点では問題ありません。
iterator.nextNode()
がコメントノードを返し、それがcurrentNode
に代入される。currentNode = iterator.nextNode()
の値は、従って真値となる。- そのため、
console.log()
の呼び出しを実行し、ループが継続される。
…そして、文書中にコメントノードがなくなったとき、次のようになります。
iterator.nextNode()
はnull
を返す。- 従って
currentNode = iterator.nextNode()
もnull
になり、これは偽値である。 - そのため、ループを終了する。
この行の問題は、条件式にはふつう比較演算子、例えば ===
を使用するものですが、この行の =
は比較演算子ではなく、代入演算子です。そのため、=
は ===
の間違いのように見えてしまいます(実際には間違いではなくても)。
従って、このようにすると、一部のコードリンティングツール、例えば ESLint の no-cond-assign
ルールなどは、誤記の可能性があるものを発見して修正しやすくするために、以下のような警告を報告します。
Expected a conditional expression and instead saw an assignment.(条件式が期待されるところに代入がありました。)
多くのスタイルガイドでは、条件式に代入式を書くことが意図的であることを、より明確に示すことを推奨しています。それを行うための最小限の方法として、括弧をグループ化演算子として追加して代入式を囲む方法があります。
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
let currentNode;
while ((currentNode = iterator.nextNode())) {
console.log(currentNode.textContent.trim());
}
実際、これは ESLint の no-cond-assign
の既定値や Prettier で強制されているスタイルなので、このパターンをよく見かけるでしょう。
条件を明示的な比較に変えるために比較演算子を追加することを勧める人もいます。
while ((currentNode = iterator.nextNode()) !== null) {
このパターンは他にも書き方があります。
while ((currentNode = iterator.nextNode()) && currentNode) {
あるいは、while
ループを使用するアイディアを完全に放棄する方法もあります。
const iterator = document.createNodeIterator(document, NodeFilter.SHOW_COMMENT);
for (
let currentNode = iterator.nextNode();
currentNode;
currentNode = iterator.nextNode()
) {
console.log(currentNode.textContent.trim());
}
読者が条件式のパターンとして代入式を記述することに十分に慣れていれば、これらの読みやすさはすべて同じくらいのはずです。そうでなければ、最も冗長ではありますが、最後の形式が最も読みやすいでしょう。
仕様書
Specification |
---|
ECMAScript Language Specification # sec-while-statement |
ブラウザーの互換性
BCD tables only load in the browser