MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
JavaScriptの基礎 - 条件分岐のソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
JavaScriptの基礎 - 条件分岐
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == JavaScriptにおける条件分岐は、プログラムの実行フローを制御するための基本的な仕組みである。<br> 条件の真偽に応じて異なる処理を実行することで、複雑なロジックを表現できる。<br> <br> JavaScriptには、条件分岐を実現するための主要な構文として、<code>if</code> / <code>else if</code> / <code>else</code>文、三項演算子 (条件演算子)、<code>switch</code>文の3つが存在する。<br> それぞれに適切な使用場面があり、状況に応じて使い分けることが重要である。<br> <br> また、JavaScriptでは条件式においてあらゆる値が真偽値として評価される。<br> この特性を、Truthy / Falsy と呼ぶ。<br> <br> Falsyな値は、<code>false</code>、<code>0</code>、<code>-0</code>、<code>0n</code>、<code>""</code>、<code>null</code>、<code>undefined</code>、<code>NaN</code> の8つに限定されており、<br> それ以外の値は全てTruthyとして扱われる。<br> <br><br> == if / else if / else == <code>if</code> 文は、最も基本的な条件分岐構文である。<br> 条件式がTruthyと評価された場合にブロック内の処理を実行し、Falsyの場合は <code>else</code> 節の処理を実行する。<br> <br> ==== 基本構文 ==== <code>if</code> 文の基本的な構文を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> if (condition) { // condition が Truthy の場合に実行される statement1; } else if (condition2) { // condition2 が Truthy の場合に実行される statement2; } else { // いずれの条件も Falsy の場合に実行される statement3; } </syntaxhighlight> <br> 使用例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const score = 75; if (score >= 90) { console.log("優"); } else if (score >= 80) { console.log("良"); } else if (score >= 70) { console.log("可"); } else { console.log("不可"); } // "可" </syntaxhighlight> <br> <code>else if</code> は任意の数を連鎖できるが、条件は上から順に評価される。<br> 最初にTruthyとなった節のブロックが実行され、以降の条件は評価されない。<br> <br> ==== ブロックと中括弧 ==== <code>if</code> 文では、中括弧 <code>{}</code> を省略して1行で記述することも文法上は可能である。<br> しかし、中括弧を省略すると、dangling else問題が発生するリスクがあり、コードの可読性が低下する。<br> <br> <syntaxhighlight lang="javascript"> // 中括弧を省略した例 (非推奨) if (condition) doSomething(); // ネストした場合に問題が発生しやすい if (a) if (b) console.log("a and b"); else console.log("?"); // このelseはどのifに属するか? (内側のif) </syntaxhighlight> <br> <syntaxhighlight lang="javascript"> // 中括弧を常に使用する (推奨) if (a) { if (b) { console.log("a and b"); } } else { console.log("not a"); // 意図が明確になる } </syntaxhighlight> <br> 中括弧を常に使用することにより、コードの意図が明確になり、後から文を追加した際のバグを防ぐことができる。<br> <br> ==== ネストしたif文 ==== <code>if</code> 文はネストして記述できるが、ネストが深くなるとコードの可読性が著しく低下する。<br> <br> <syntaxhighlight lang="javascript"> // ネストが深い例 (可読性が低い) function processUser(user) { if (user) { if (user.isActive) { if (user.isVerified) { console.log("ユーザー処理を続行"); // 本来の処理 } } } } </syntaxhighlight> <br> このような場合は、ガード節 (早期リターン) パターンを用いてネストを解消することが推奨される。<br> <br> <syntaxhighlight lang="javascript"> // ガード節を使用した例 (可読性が高い) function processUser(user) { if (!user) return; if (!user.isActive) return; if (!user.isVerified) return; console.log("ユーザ処理を続行"); // 本来の処理 } </syntaxhighlight> <br> ガード節パターンでは、無効な条件を先頭で早期に除外することで、メインロジックをフラットな構造で記述できる。<br> <br> ==== 条件式のパターン ==== <code>if</code> 文の条件式には、様々なパターンが使用できる。<br> <br> * 等値比較 *: 値の一致を確認する際は、型変換を行わない厳密等価演算子 (<code>===</code>) を使用することが推奨される。 *: <syntaxhighlight lang="javascript"> const status = "active"; if (status === "active") { console.log("アクティブなユーザー"); } // == は型変換を行うため予期しない動作になる可能性がある (非推奨) if (status == "active") { } </syntaxhighlight> *: <br> * 範囲チェック *: 数値が特定の範囲内にあるかどうかを確認するパターンである。 *: <syntaxhighlight lang="javascript"> const age = 25; if (age >= 18 && age < 65) { console.log("成人 (就労年齢)"); } </syntaxhighlight> *: <br> * 存在確認 *: オブジェクトのプロパティや変数の値が存在するかどうかを確認するパターンである。 *: <syntaxhighlight lang="javascript"> const user = { name: "Alice", profile: { bio: "Developer" } }; if (user.profile) { console.log(user.profile.bio); } // null または undefined の両方を除外する厳密な確認 if (user.profile !== null && user.profile !== undefined) { console.log(user.profile.bio); } </syntaxhighlight> *: <br> * typeof演算子を使用した型チェック *: <syntaxhighlight lang="javascript"> function greet(value) { if (typeof value === "string") { console.log("こんにちは、" + value + "さん"); } else if (typeof value === "number") { console.log("番号: " + value); } else { console.log("不明な値: " + value); } } greet("Alice"); // "こんにちは、Aliceさん" greet(42); // "番号: 42" </syntaxhighlight> <br><br> == 三項演算子 (条件演算子) == 三項演算子 (条件演算子) は、JavaScriptで唯一の3つのオペランドを取る演算子である。<br> 簡潔な条件分岐を式として記述でき、変数への代入や関数の引数として使用できる。<br> <br> ==== 基本構文 ==== 三項演算子の構文は以下の通りである。<br> <br> <syntaxhighlight lang="javascript"> condition ? exprIfTrue : exprIfFalse </syntaxhighlight> <br> <code>condition</code> がTruthyの場合は <code>exprIfTrue</code> が評価されて返され、Falsyの場合は <code>exprIfFalse</code> が評価されて返される。<br> <br> 使用例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const age = 25; const beverage = age >= 21 ? "Beer" : "Juice"; console.log(beverage); // "Beer" // 関数の引数での使用 console.log(age >= 20 ? "成人" : "未成年"); // テンプレートリテラル内での使用 const isLoggedIn = true; const greeting = `ようこそ、${isLoggedIn ? "ユーザー" : "ゲスト"}さん`; console.log(greeting); // "ようこそ、ユーザーさん" </syntaxhighlight> <br> ==== if文との使い分け ==== 三項演算子と <code>if</code> 文は、使用場面が異なる。<br> <br> * 三項演算子が適している場合 ** 単純な値の決定 (2つの選択肢から1つを選ぶ) ** 変数への代入 ** 式として評価される文脈 (テンプレートリテラル、JSXなど) *: <br> * <code>if</code> 文が適している場合 ** 複数行にわたる処理 ** 副作用を伴う処理 (関数呼び出し、ログ出力等) ** 複雑な条件ロジック <br> <syntaxhighlight lang="javascript"> // 三項演算子が適切な例: 値の決定 const label = isActive ? "有効" : "無効"; const discount = isMember ? price * 0.8 : price; // if文が適切な例: 複数行の処理 if (isActive) { user.activate(); sendWelcomeEmail(user); console.log("アクティベート完了"); } else { user.deactivate(); console.log("無効化完了"); } </syntaxhighlight> <br> ==== ネストした三項演算子 ==== 三項演算子はネストして連鎖させることが可能であるが、一般的に非推奨である。<br> <br> <syntaxhighlight lang="javascript"> // ネストした三項演算子 (非推奨: 可読性が低い) const score = 75; const grade = score >= 90 ? "優" : score >= 80 ? "良" : score >= 70 ? "可" : "不可"; </syntaxhighlight> <br> このような複数の条件分岐が必要な場合は、<code>if</code> / <code>else if</code> 文を使用することが推奨される。<br> <br> <syntaxhighlight lang="javascript"> // if / else if を使用した例 (推奨: 可読性が高い) let grade; if (score >= 90) { grade = "優"; } else if (score >= 80) { grade = "良"; } else if (score >= 70) { grade = "可"; } else { grade = "不可"; } </syntaxhighlight> <br><br> == switch文 == <code>switch</code> 文は、1つの式を複数の値と比較する際に用いる条件分岐構文である。<br> 複数の選択肢がある場合に、<code>if</code> / <code>else if</code> の連鎖よりも可読性が高くなることがある。<br> <br> ==== 基本構文 ==== <code>switch</code> 文の基本的な構文を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> switch (expression) { case value1: // expression === value1 の場合に実行される statements; break; case value2: // expression === value2 の場合に実行される statements; break; default: // いずれのcaseにも一致しない場合に実行される statements; } </syntaxhighlight> <br> <code>switch</code> 文は、expressionの値を各caseの値と厳密等価演算子 (<code>===</code>) で比較する。<br> <code>default</code> 節は省略可能であるが、予期しない値への対処のため記述することが推奨される。<br> <br> 使用例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const day = "Monday"; switch (day) { case "Monday": console.log("月曜日: 週の始まり"); break; case "Friday": console.log("金曜日: 週の終わり"); break; case "Saturday": case "Sunday": console.log("週末"); break; default: console.log("平日"); } // "月曜日: 週の始まり" </syntaxhighlight> <br> ==== breakとフォールスルー ==== <code>switch</code> 文において、<code>break</code>文はブロックの実行を終了して <code>switch</code> 文から抜け出す役割を担う。<br> <br> <code>break</code> 文を省略すると、フォールスルー (fall-through) が発生し、次のcaseの処理も続けて実行される。<br> <br> <syntaxhighlight lang="javascript"> // フォールスルーが発生する例 const num = 1; switch (num) { case 1: console.log("1"); // 実行される case 2: console.log("2"); // break がないため続けて実行される case 3: console.log("3"); // break がないため続けて実行される break; case 4: console.log("4"); // 実行されない } // "1", "2", "3" が全て出力される </syntaxhighlight> <br> フォールスルーは通常バグの原因となるため、意図的に使用する場合はコメントで明示することが推奨される。<br> <br> <syntaxhighlight lang="javascript"> // 意図的なフォールスルー (コメントで明示する) switch (command) { case "save": case "write": // "save" と "write" で同じ処理を行う (意図的なフォールスルー) saveToFile(); break; case "quit": case "exit": // "quit" と "exit" で同じ処理を行う (意図的なフォールスルー) closeApplication(); break; } </syntaxhighlight> <br> ==== switch文の応用 ==== <code>switch</code> 文には、基本的な使い方以外にもいくつかの応用パターンが存在する。<br> <br> * グルーピング *: 複数の <code>case</code> で同じ処理を実行したい場合、<code>case</code> を連続して並べることでグルーピングできる。 *: <syntaxhighlight lang="javascript"> const month = 4; let season; switch (month) { case 3: case 4: case 5: season = "春"; break; case 6: case 7: case 8: season = "夏"; break; case 9: case 10: case 11: season = "秋"; break; default: season = "冬"; } console.log(season); // "春" </syntaxhighlight> *: <br> * <code>switch(true)</code> パターン *: <code>switch</code>文の式に <code>true</code> を指定し、各 <code>case</code> で条件式を記述するパターンである。 *: 複雑な条件式を <code>switch</code> 構造で整理したい場合に有用である。 *: <syntaxhighlight lang="javascript"> const score = 75; let grade; switch (true) { case score >= 90: grade = "優"; break; case score >= 80: grade = "良"; break; case score >= 70: grade = "可"; break; default: grade = "不可"; } console.log(grade); // "可" </syntaxhighlight> *: <br> * ブロックスコープ *: <code>case</code> 節内で <code>let</code> / <code>const</code> を使用する場合、同じ <code>switch</code>ブロック内で変数名が衝突する可能性がある。 *: この問題を回避するには、<code>case</code> 節を中括弧で囲んで独立したブロックスコープを作成する。 *: <syntaxhighlight lang="javascript"> switch (action) { case "create": { const id = generateId(); // このブロック内のみで有効 const item = createItem(id); console.log(item); break; } case "delete": { const id = getSelectedId(); // 別ブロックなので同名でもOK deleteItem(id); break; } } </syntaxhighlight> <br> ==== if文との使い分け ==== <code>switch</code> 文 と <code>if</code> 文はそれぞれ異なる場面に適している。<br> <br> 下表に比較を示す。<br> <br> <center> {| class="wikitable" |+ if文とswitch文の比較 ! 観点 !! if文 !! switch文 |- | 比較の種類 || あらゆる条件式 (範囲比較、関数の戻り値など) || 1つの式を複数の値と比較 |- | 比較演算子 || ===、!==、<、>、&&、<nowiki>||</nowiki> 等、自由に指定 || === のみ (厳密等価) |- | 型の比較 || あらゆる型の条件式 || プリミティブ値との厳密等価 |- | 可読性 || 条件が少ない場合や複雑な条件式に適する || 同一の式を複数の値と比較する場合に適する |- | フォールスルー || なし || あり (breakを省略すると発生) |- | デフォルト処理 || else節 || default節 |- | 適した場面 || 範囲チェック、複雑なロジック、型チェック || 列挙型、固定の文字列・数値との比較 |} </center> <br> <syntaxhighlight lang="javascript"> // switch文が適した例: 固定の文字列との比較 switch (statusCode) { case 200: console.log("OK"); break; case 404: console.log("Not Found"); break; case 500: console.log("Internal Server Error"); break; default: console.log("その他"); } // if文が適した例: 範囲比較 if (temperature >= 35) { console.log("猛暑"); } else if (temperature >= 25) { console.log("夏日"); } else if (temperature >= 0) { console.log("通常"); } else { console.log("氷点下"); } </syntaxhighlight> <br><br> == Truthy / Falsy == JavaScriptでは、<code>if</code> 文等の条件式においてあらゆる値が自動的に真偽値へ変換される。<br> この時、<code>false</code> と評価される値をFalsy、<code>true</code> と評価される値をTruthyと呼ぶ。<br> <br> ==== Falsy値一覧 ==== JavaScriptにおけるFalsy値は以下の8つのみである。<br> これら以外の全ての値は、Truthyとなる。<br> <br> <center> {| class="wikitable" |+ Falsy値一覧 ! 値 !! 型 !! 説明 |- | false || Boolean || ブール値の false |- | 0 || Number || 数値のゼロ |- | -0 || Number || 負のゼロ |- | 0n || BigInt || BigInt のゼロ |- | "" || String || 空文字列 (長さ0の文字列) |- | null || Null || 値の意図的な欠落 |- | undefined || Undefined || 未定義 (値が代入されていない) |- | NaN || Number || 非数値 (Not a Number) |} </center> <br> <syntaxhighlight lang="javascript"> // 各Falsy値の確認 if (false) { } // 実行されない if (0) { } // 実行されない if (-0) { } // 実行されない if (0n) { } // 実行されない if ("") { } // 実行されない if (null) { } // 実行されない if (undefined) { } // 実行されない if (NaN) { } // 実行されない // Boolean()による明示的な変換で確認 console.log(Boolean(false)); // false console.log(Boolean(0)); // false console.log(Boolean("")); // false console.log(Boolean(null)); // false console.log(Boolean(undefined)); // false console.log(Boolean(NaN)); // false </syntaxhighlight> <br> ==== 注意が必要なTruthy値 ==== 一見、Falsyのように思えるが、実際にはTruthyと評価される値が存在する。<br> これらはバグの原因になりやすいため、特に注意が必要である。<br> <br> * <code>"0"</code> (文字列のゼロ) *: 数値の <u>0</u> はFalsyだが、文字列 <u>"0"</u> は空文字列ではないためTruthyである。 * <code>"false"</code> (文字列のfalse) *: ブール値の <u>false</u> はFalsyだが、文字列 <u>"false"</u> はTruthyである。 * <code>[]</code> (空の配列) *: 空の配列はオブジェクトであるため、Truthyである。 * <code>{}</code> (空のオブジェクト) *: 空のオブジェクトもTruthyである。 <br> <syntaxhighlight lang="javascript"> // 注意が必要なTruthy値 console.log(Boolean("0")); // true (文字列 "0" は Truthy) console.log(Boolean("false")); // true (文字列 "false" は Truthy) console.log(Boolean([])); // true (空配列は Truthy) console.log(Boolean({})); // true (空オブジェクトは Truthy) // よくある誤り const value = "0"; if (value) { console.log("Truthy"); // こちらが実行される } else { console.log("Falsy"); // 実行されない } // 空配列の確認は、lengthプロパティを使用する const arr = []; if (arr.length === 0) { console.log("空の配列"); // 正しいチェック方法 } </syntaxhighlight> <br> ==== 条件分岐での活用 ==== Truthy / Falsyの特性を利用することで、簡潔な条件分岐を記述できる。<br> <br> <syntaxhighlight lang="javascript"> const user = getUserFromDB(); // userがnullまたはundefinedでないかを確認 if (user) { console.log("ユーザーが存在する: " + user.name); } // 文字列の存在確認 const message = getMessage(); if (message) { displayMessage(message); } // 配列の存在および要素確認 (要素数も考慮する場合は、lengthを使用) const items = getItems(); if (items && items.length > 0) { renderList(items); } </syntaxhighlight> <br> ==== 暗黙の型変換に関する注意点 ==== 条件式で暗黙の型変換が行われることにより、意図しない動作が生じる場合がある。<br> 明示的な比較を記述することで、こうした問題を回避できる。<br> <br> <syntaxhighlight lang="javascript"> // 暗黙の型変換による問題 function processCount(count) { // count が 0 の場合、Falsy と判定されて処理がスキップされる if (count) { console.log("件数: " + count); } } processCount(0); // 何も出力されない (意図しない動作) // 明示的な比較で解決する function processCountFixed(count) { if (count !== null && count !== undefined) { console.log("件数: " + count); } } processCountFixed(0); // "件数: 0" (正しく動作する) </syntaxhighlight> <br> <syntaxhighlight lang="javascript"> // 数値の存在確認には、typeofを使用する function isValidNumber(value) { return typeof value === "number" && !isNaN(value); } console.log(isValidNumber(0)); // true (0 は有効な数値) console.log(isValidNumber(null)); // false console.log(isValidNumber(undefined)); // false console.log(isValidNumber(NaN)); // false </syntaxhighlight> <br> <u>null</u> と <u>undefined</u> のみを除外したい場合は、Null合体演算子 (<code>??</code>) の使用も検討する。<br> <code>??</code> は <u>null</u> と <u>undefined</u> のみをFalsyとして扱うため、<u>0</u> や <u>""</u> が有効な値として扱われる。<br> <br><br> == 実用的な条件分岐パターン == 実際の開発でよく使用される条件分岐のパターンを以下に示す。<br> <br> ==== ガード節 (早期リターン) ==== ガード節 (Guard Clause) は、関数の先頭で無効な条件を早期に除外するパターンである。<br> ネストを浅く保ち、ソースコードの可読性を向上させることができる。<br> <br> <syntaxhighlight lang="javascript"> // ネストが深い例 (避けるべきパターン) function sendEmail(user) { if (user) { if (user.email) { if (user.isSubscribed) { if (user.isVerified) { // メール送信処理 mailer.send(user.email, "Welcome!"); } } } } } </syntaxhighlight> <br> <syntaxhighlight lang="javascript"> // ガード節を使用した例 (推奨パターン) function sendEmail(user) { if (!user) return; if (!user.email) return; if (!user.isSubscribed) return; if (!user.isVerified) return; // 全ての条件を満たした場合のメイン処理 mailer.send(user.email, "Welcome!"); } </syntaxhighlight> <br> ガード節パターンのメリットを以下に示す。<br> <br> * ネストが浅くなりコードが読みやすくなる。 * 各条件の意図が明確になる。 * メインロジックが最後にフラットな形で記述される。 * 単体試験が書きやすくなる。 <br> 入力検証パターンにガード節を適用した例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> function createUser(name, age, email) { // 入力検証 (ガード節) if (typeof name !== "string" || name.trim() === "") { throw new Error("名前は必須です"); } if (typeof age !== "number" || age < 0 || age > 150) { throw new Error("年齢が無効です"); } if (typeof email !== "string" || !email.includes("@")) { throw new Error("メールアドレスが無効です"); } // 検証を通過した場合のメイン処理 return { name: name.trim(), age, email }; } </syntaxhighlight> <br> ==== オブジェクトルックアップ ==== オブジェクトルックアップは、<code>switch</code> 文の代替として使用できるパターンである。<br> キーと値のマッピングをオブジェクトとして定義し、動的にアクセスすることで条件分岐を簡潔に表現できる。<br> <br> <syntaxhighlight lang="javascript"> // switch文を使用した場合 function getStatusColor(status) { switch (status) { case "success": return "green"; case "warning": return "orange"; case "error": return "red"; case "info": return "blue"; default: return "gray"; } } </syntaxhighlight> <br> <syntaxhighlight lang="javascript"> // オブジェクトルックアップを使用した場合 const statusColors = { success: "green", warning: "orange", error: "red", info: "blue", }; function getStatusColor(status) { return statusColors[status] ?? "gray"; } console.log(getStatusColor("success")); // "green" console.log(getStatusColor("unknown")); // "gray" </syntaxhighlight> <br> 関数をオブジェクトの値として格納することで、より複雑な処理にも対応できる。<br> <br> <syntaxhighlight lang="javascript"> // 関数をオブジェクトの値として格納するパターン const actions = { increment: (count) => count + 1, decrement: (count) => count - 1, reset: (_) => 0, }; function applyAction(action, count) { const fn = actions[action]; if (!fn) { throw new Error("不明なアクション: " + action); } return fn(count); } console.log(applyAction("increment", 5)); // 6 console.log(applyAction("decrement", 5)); // 4 console.log(applyAction("reset", 5)); // 0 </syntaxhighlight> <br> オブジェクトルックアップパターンのメリットを以下に示す。<br> <br> * ソースコードが簡潔になる。 * 新しい選択肢の追加がオブジェクトへの1行追加で済む。 * オブジェクト自体を外部から注入したり動的に変更することができる。 * フォールスルーの心配がない。 <br><br> == 関連情報 == * [[JavaScriptの基礎 - 変数宣言]] *: let / const / varの宣言方法、スコープ、ホイスティング * [[JavaScriptの基礎 - プリミティブ型]] *: 7つのプリミティブ型、typeof演算子、型の自動変換 * [[JavaScriptの基礎 - 比較演算子と論理演算子]] *: === / ==の違い、短絡評価、Null合体演算子、オプショナルチェーン * [[JavaScriptの基礎 - 反復処理(for文)]] *: for文、for...of、for...in、使い分け * [[JavaScriptの基礎 - 反復処理(while文)]] *: while文、do...while文、break / continue、無限ループ回避 <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
JavaScriptの基礎 - 条件分岐
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse