diff --git a/1-js/02-first-steps/13-while-for/article.md b/1-js/02-first-steps/13-while-for/article.md index 437f67e9c..47ef53112 100644 --- a/1-js/02-first-steps/13-while-for/article.md +++ b/1-js/02-first-steps/13-while-for/article.md @@ -1,65 +1,66 @@ -# การวนซ้ำ (Loops): while และ for +# วงวน (Loops): while และ for -เราจำเป็นต้องทำซ้ำคำสั่งบ่อยๆ +เราจำเป็นต้องทำคำสั่งซ้ำๆ บ่อยครั้ง -ยกตัวอย่างเช่น การแสดงสินค้าจากรายการออกมาทีละชิ้น หรือแค่รันโค้ดเดิมซ้ำๆ กับตัวเลขแต่ละตัวจาก 1 ถึง 10 +ยกตัวอย่างเช่น การแสดงสินค้าในรายการทีละชิ้น หรือการรันโค้ดเดิมซ้ำๆ กับตัวเลขตั้งแต่ 1 ถึง 10 -*Loops* คือวิธีการที่ใช้ในการทำซ้ำโค้ดเดิมหลายๆ ครั้ง +*วงวน (Loops)* คือวิธีการทำซ้ำโค้ดเดิมหลายๆ รอบ -```smart header="การวนซ้ำ for..of และ for..in" +```smart header="วงวน for..of และ for..in" ประกาศสำหรับผู้อ่านขั้นสูง -บทความนี้ครอบคลุมเฉพาะ loops พื้นฐาน: `while`, `do..while` และ `for(..;..;..)` +บทความนี้กล่าวถึงวงวนพื้นฐานเท่านั้น ได้แก่ `while`, `do..while` และ `for(..;..;..)` -ถ้าคุณมาถึงบทความนี้เพื่อค้นหาประเภทอื่นๆ ของ loops ลองดูที่นี่: -- ดู [for..in](info:object#forin) สำหรับการวนซ้ำคุณสมบัติของออบเจ็กต์ -- ดู [for..of](info:array#loops) และ [iterables](info:iterable) สำหรับการวนซ้ำอาร์เรย์และออบเจ็กต์ที่สามารถวนซ้ำได้ +ถ้าคุณมาที่บทความนี้เพื่อหาวงวนประเภทอื่นๆ ลองดูตรงนี้: -ถ้าไม่ใช่ ขอให้อ่านต่อไป +- ดู [for..in](info:object#forin) สำหรับการวนซ้ำ property ของ object +- ดู [for..of](info:array#loops) และ [iterables](info:iterable) สำหรับการวนซ้ำ array และ iterable objects + +มิฉะนั้นก็อ่านต่อได้เลย ``` -## การวนซ้ำแบบ "while" +## วงวน "while" -การวนซ้ำแบบ `while` มีรูปแบบดังนี้: +วงวน `while` มีรูปแบบไวยากรณ์ดังนี้: ```js -while (เงื่อนไข) { - // โค้ด +while (condition) { + // code // เรียกว่า "loop body" } ``` -ในขณะที่ `เงื่อนไข` ยังเป็นจริง `โค้ด` ใน loop body จะถูกรัน +ตราบใดที่ `condition` ยังเป็นจริง `code` ใน loop body ก็จะถูกรัน -ยกตัวอย่างเช่น loop ด้านล่างจะแสดง `i` ตราบใดที่ `i < 3`: +ยกตัวอย่างเช่น วงวนด้านล่างจะแสดง `i` ตราบใดที่ `i < 3`: ```js run let i = 0; -while (i < 3) { // แสดง 0, จากนั้น 1, จากนั้น 2 +while (i < 3) { // แสดง 0, แล้ว 1, แล้ว 2 alert( i ); i++; } ``` -การรันโค้ดใน loop body หนึ่งรอบ เรียกว่า *an iteration* loop ในตัวอย่างด้านบน จะทำ 3 iterations +การรันโค้ดใน loop body หนึ่งรอบเรียกว่า *อิเทอเรชัน (iteration)* วงวนในตัวอย่างข้างต้นจะทำ 3 อิเทอเรชัน -ถ้าไม่มีการเพิ่ม `i++` ใน loop จะวนซ้ำไปเรื่อยๆ (ในทางทฤษฎี) ในทางปฏิบัติ เบราว์เซอร์จะมีวิธีการในการหยุด loop แบบนี้ และใน JavaScript ฝั่งเซิร์ฟเวอร์ เราสามารถหยุดกระบวนการได้ +ถ้าขาด `i++` ในตัวอย่าง วงวนจะทำซ้ำไปตลอด (ในทางทฤษฎี) แต่ในทางปฏิบัติ เบราว์เซอร์จะมีวิธีหยุดวงวนแบบนี้ และใน JavaScript ฝั่งเซิร์ฟเวอร์ เราก็หยุดโพรเซสได้ -นิพจน์หรือตัวแปรใดก็ได้สามารถใช้เป็นเงื่อนไขในการวนซ้ำได้ ไม่จำกัดแค่เป็นการเปรียบเทียบเท่านั้น: เงื่อนไขจะถูกประเมินและแปลงเป็น boolean โดย `while` +นิพจน์หรือตัวแปรใดๆ ก็ตามสามารถใช้เป็นเงื่อนไขวงวนได้ ไม่จำกัดแค่การเปรียบเทียบ: `while` จะประเมินเงื่อนไขและแปลงเป็น boolean -ตัวอย่างเช่น วิธีที่สั้นกว่า `while (i != 0)` คือ `while (i)`: +เช่น วิธีเขียน `while (i != 0)` ให้สั้นลงคือ `while (i)`: ```js run let i = 3; *!* -while (i) { // เมื่อ i เป็น 0, เงื่อนไขจะเป็น falsy แล้ว loop จะหยุด +while (i) { // เมื่อ i เป็น 0, เงื่อนไขจะเป็น falsy และวงวนจะหยุด */!* alert( i ); i--; } ``` -````smart header="ไม่ต้องใส่ปีกกา { } ถ้า loop body มีแค่คำสั่งเดียว" +````smart header="ไม่ต้องใส่ปีกกา { } ถ้า loop body มีคำสั่งเดียว" ถ้า loop body มีแค่คำสั่งเดียว เราสามารถละปีกกา `{…}` ได้: ```js run @@ -70,19 +71,19 @@ while (i) alert(i--); ``` ```` -## การวนซ้ำแบบ "do..while" +## วงวน "do..while" -การตรวจสอบเงื่อนไขสามารถย้ายไปอยู่ *ข้างล่าง* loop body ได้ ด้วยการใช้ `do..while`: +การตรวจสอบเงื่อนไขสามารถย้ายไปอยู่*ใต้* loop body ได้โดยใช้ `do..while`: ```js do { // loop body -} while (เงื่อนไข); +} while (condition); ``` -Loop จะรันโค้ดใน body ก่อน แล้วค่อยมาตรวจสอบเงื่อนไข และถ้าเงื่อนไขเป็นจริง ก็จะรันซ้ำไปเรื่อยๆ +วงวนจะรัน loop body ก่อน จากนั้นจึงตรวจสอบเงื่อนไข และหากเงื่อนไขเป็นจริง ก็จะรันซ้ำแล้วซ้ำอีก -ตัวอย่าง: +ตัวอย่างเช่น: ```js run let i = 0; @@ -92,38 +93,38 @@ do { } while (i < 3); ``` -รูปแบบนี้ควรใช้เฉพาะตอนที่คุณต้องการให้ loop body รันอย่างน้อยหนึ่งครั้ง ไม่ว่าเงื่อนไขจะเป็นจริงหรือไม่ก็ตาม ในกรณีทั่วไป ควรเลือกใช้รูปแบบ `while(…) {…}` มากกว่า +ควรใช้รูปแบบไวยากรณ์นี้เฉพาะเมื่อต้องการให้ loop body รันอย่างน้อย**หนึ่งครั้ง** โดยไม่คำนึงว่าเงื่อนไขจะเป็นจริงหรือไม่ โดยปกติแล้วมักนิยมใช้รูปแบบ `while(…) {…}` มากกว่า -## การวนซ้ำแบบ "for" +## วงวน "for" -การวนซ้ำแบบ `for` มีความซับซ้อนมากกว่า แต่ก็เป็นรูปแบบที่นิยมใช้มากที่สุดเช่นกัน +วงวน `for` มีความซับซ้อนมากกว่า แต่ก็เป็นวงวนที่ใช้กันบ่อยที่สุดเช่นกัน -มีรูปแบบดังนี้: +รูปแบบคือ: ```js -for (เริ่มต้น; เงื่อนไข; ขั้นตอน) { +for (begin; condition; step) { // ... loop body ... } ``` -ลองมาศึกษาความหมายของแต่ละส่วนจากตัวอย่างกัน loop ด้านล่างจะรัน `alert(i)` เมื่อ `i` มีค่าตั้งแต่ `0` ถึง `3` (ไม่รวม `3`): +มาดูความหมายของแต่ละส่วนจากตัวอย่างกัน วงวนด้านล่างจะรัน `alert(i)` สำหรับ `i` ตั้งแต่ `0` ถึง `3` (ไม่รวม `3`): ```js run -for (let i = 0; i < 3; i++) { // แสดง 0, จากนั้น 1, จากนั้น 2 +for (let i = 0; i < 3; i++) { // แสดง 0, แล้ว 1, แล้ว 2 alert(i); } ``` -มาดูแต่ละส่วนของคำสั่ง `for` กัน: +มาดูคำสั่ง `for` ทีละส่วน: -| ส่วน | | | -|-------|----------|----------------------------------------------------------------------------| -| เริ่มต้น | `let i = 0` | รันครั้งเดียวตอนเข้า loop | -| เงื่อนไข | `i < 3`| ตรวจสอบก่อนทุกรอบของ loop ถ้าเป็น false loop จะหยุด | -| body | `alert(i)`| รันซ้ำๆ ตราบใดที่เงื่อนไขยังเป็นจริง | -| ขั้นตอน| `i++` | รันหลังจาก body ในแต่ละรอบ | +| ส่วน | | | +|-----------|---------------|-------------------------------------------------------------------------------| +| begin | `let i = 0` | รันครั้งเดียวตอนเข้าวงวน | +| condition | `i < 3` | ถูกตรวจสอบก่อนการรันวงวนแต่ละรอบ ถ้าเป็น false วงวนจะหยุด | +| body | `alert(i)` | รันซ้ำไปเรื่อยๆ ตราบใดที่ condition ยังเป็นจริง | +| step | `i++` | รันหลัง body ในแต่ละรอบ | -อัลกอริทึมทั่วไปของ loop จะทำงานดังนี้: +อัลกอริทึมทั่วไปของวงวนทำงานแบบนี้: ``` รันส่วนเริ่มต้น @@ -133,11 +134,11 @@ for (let i = 0; i < 3; i++) { // แสดง 0, จากนั้น 1, จา → ... ``` -ถ้าพูดให้ชัดเจน `เริ่มต้น` จะรันครั้งเดียว แล้วก็จะเข้าสู่ iteration: หลังจากการตรวจสอบ `เงื่อนไข` `body` และ `ขั้นตอน` จะถูกรัน +นั่นคือ `begin` รันครั้งเดียว แล้วก็จะเข้าสู่ iteration: หลังจากทดสอบ `condition` แล้ว `body` และ `step` จะถูกรัน -ถ้าคุณใหม่กับ loops การกลับไปอ่านตัวอย่างพร้อมๆ กับเขียนว่าแต่ละขั้นตอนทำงานอย่างไรก็อาจจะช่วยได้ +ถ้าคุณใหม่กับวงวน การย้อนกลับไปดูตัวอย่างพร้อมๆ กับเขียนว่าแต่ละขั้นตอนทำงานอย่างไร อาจจะช่วยให้เข้าใจได้ดีขึ้น -นี่คือสิ่งที่เกิดขึ้นในตัวอย่างของเรา: +ต่อไปนี้คือสิ่งที่เกิดขึ้นจริงๆ ในตัวอย่างของเรา: ```js // for (let i = 0; i < 3; i++) alert(i) @@ -153,81 +154,81 @@ if (i < 3) { alert(i); i++ } // ...เสร็จสิ้น เพราะตอนนี้ i == 3 ``` -````smart header="ประกาศตัวแปรใน loop" -ในตัวอย่าง ตัวแปร "counter" `i` ถูกประกาศภายใน loop โดยตรง นี่เรียกว่า "inline" variable declaration ตัวแปรเหล่านี้จะมองเห็นเฉพาะใน loop เท่านั้น +````smart header="การประกาศตัวแปรใน loop" +ในที่นี้ ตัวแปร "counter" `i` ถูกประกาศในวงวนโดยตรง เรียกว่าการประกาศตัวแปร "inline" ตัวแปรเหล่านี้จะมองเห็นได้เฉพาะในวงวนเท่านั้น ```js run for (*!*let*/!* i = 0; i < 3; i++) { alert(i); // 0, 1, 2 } alert(i); // error, ไม่มีตัวแปรนี้ -``` +``` -แทนที่จะประกาศตัวแปรใหม่ เราสามารถใช้ตัวแปรที่มีอยู่แล้วได้: +แทนที่จะประกาศตัวแปรใหม่ เราสามารถใช้ตัวแปรที่มีอยู่แล้ว: ```js run let i = 0; -for (i = 0; i < 3; i++) { // ใช้ตัวแปรที่มีอยู่แล้ว - alert(i); // 0, 1, 2 +for (i = 0; i < 3; i++) { // ใช้ตัวแปรที่มีอยู่ + alert(i); // 0, 1, 2 } -alert(i); // 3, มองเห็น เพราะประกาศนอก loop +alert(i); // 3, มองเห็นได้ เพราะถูกประกาศนอกวงวน ``` ```` -### การข้ามส่วน +### การข้ามส่วนต่างๆ ของวงวน -เราสามารถข้ามส่วนใดส่วนหนึ่งของ `for` ได้ +เราสามารถข้ามส่วนใดๆ ของ `for` ก็ได้ -ยกตัวอย่างเช่น เราสามารถละ `เริ่มต้น` ได้ถ้าเราไม่ต้องทำอะไรตอนเริ่ม loop +ยกตัวอย่างเช่น เราสามารถละส่วน `begin` ได้ ถ้าเราไม่จำเป็นต้องทำอะไรที่จุดเริ่มต้นของวงวน -อย่างเช่นที่นี่: +เช่นในตัวอย่างนี้: ```js run -let i = 0; // เราประกาศ i ไว้แล้วก่อนหน้านี้ +let i = 0; // เรามีการประกาศและกำหนดค่า i ไว้ก่อนแล้ว -for (; i < 3; i++) { // ไม่จำเป็นต้องมี "เริ่มต้น" +for (; i < 3; i++) { // ไม่จำเป็นต้องมีส่วน "begin" alert( i ); // 0, 1, 2 } ``` -เราสามารถละส่วน `ขั้นตอน` ได้เช่นกัน: +เราสามารถตัดส่วน `step` ออกได้ด้วย: ```js run let i = 0; for (; i < 3;) { alert( i++ ); -} +} ``` -นี่จะทำให้ loop เหมือนกับ `while (i < 3)` +การทำแบบนี้จะทำให้วงวนเหมือนกับ `while (i < 3)` -เราสามารถลบได้ทุกอย่างเลย เพื่อสร้าง infinite loop: +จริงๆ แล้วเราสามารถตัดทุกอย่างออกได้เลย เพื่อสร้างวงวนอนันต์: ```js for (;;) { - // วนซ้ำไม่มีที่สิ้นสุด + // ทำซ้ำไม่รู้จบ } ``` -โปรดทราบว่า semicolon `;` ทั้งสองใน `for` ต้องมีนะ ไม่อย่างนั้นจะเป็น syntax error +โปรดสังเกตว่าเครื่องหมายอัฒภาค `;` สองตัวของ `for` ต้องมี ไม่อย่างนั้นจะเกิด syntax error -## การหยุด loop +## การออกจากวงวน -โดยปกติ loop จะหยุดเมื่อเงื่อนไขเป็น falsy +โดยปกติ วงวนจะจบลงเมื่อเงื่อนไขเป็น falsy -แต่เราสามารถบังคับให้หยุดเมื่อไรก็ได้ด้วยคำสั่ง `break` +แต่เราสามารถบังคับให้ออกจากวงวนเมื่อไรก็ได้ โดยใช้คำสั่ง `break` -ยกตัวอย่างเช่น loop ด้านล่างจะถามผู้ใช้ให้กรอกตัวเลข และจะ "break" เมื่อไม่มีการป้อนตัวเลข: +ตัวอย่างเช่น วงวนด้านล่างจะขอให้ผู้ใช้ป้อนชุดของตัวเลข และจะ "ออกจากวงวน" เมื่อไม่มีการป้อนตัวเลข: ```js run let sum = 0; while (true) { - let value = +prompt("ใส่ตัวเลข", ''); + let value = +prompt("ป้อนตัวเลข", ''); *!* if (!value) break; // (*) @@ -239,32 +240,32 @@ while (true) { alert( 'ผลรวม: ' + sum ); ``` -คำสั่ง `break` จะถูกเรียกที่บรรทัด `(*)` ถ้าผู้ใช้ป้อนบรรทัดว่าง หรือกด cancel มันจะหยุด loop ในทันที และส่งการทำงานไปยังบรรทัดแรกหลัง loop นั่นคือ `alert` +คำสั่ง `break` จะทำงานที่บรรทัด `(*)` หากผู้ใช้ป้อนค่าว่างหรือกดยกเลิก มันจะหยุดวงวนทันทีแล้วส่งการควบคุมไปที่บรรทัดแรกหลังวงวน นั่นคือ `alert` -การผสมผสานของ "infinite loop + `break` เมื่อต้องการ" เหมาะสำหรับสถานการณ์ที่ต้องการตรวจสอบเงื่อนไขในกลางหรือหลายตำแหน่งในส่วน body ของลูป +การใช้ "วงวนอนันต์ + `break` เมื่อจำเป็น" เป็นวิธีที่ดีสำหรับสถานการณ์ที่ต้องตรวจเช็คเงื่อนไขวงวน ไม่ใช่ที่จุดเริ่มต้นหรือจุดสิ้นสุด แต่อยู่ตรงกลางหรือหลายๆ ที่ในวงวน -## การข้ามไปยัง Iteration ถัดไป [#continue] +## การข้ามไปทำรอบถัดไป [#continue] -คำสั่ง `continue` เป็น "เวอร์ชันเบาๆ" ของ `break` มันไม่ได้หยุด loop ทั้งหมด แต่มันจะหยุด iteration ปัจจุบัน และบังคับให้ loop เริ่มใหม่ (ถ้าเงื่อนไขอนุญาต) +คำสั่ง `continue` เป็น "เวอร์ชันที่เบากว่า" ของ `break` มันไม่ได้หยุดวงวนทั้งหมด แต่จะหยุดการทำงานในรอบปัจจุบันแล้วบังคับให้วงวนเริ่มรอบใหม่ (ถ้าเงื่อนไขอนุญาต) -เราสามารถใช้มันได้ถ้าเราทำส่วนปัจจุบันเสร็จแล้ว และต้องการไปยังรอบถัดไป +เราสามารถใช้มันได้ถ้าเราเสร็จงานในรอบปัจจุบันแล้ว และต้องการข้ามไปทำรอบถัดไปเลย -Loop ด้านล่างใช้ `continue` เพื่อแสดงผลเฉพาะค่าที่เป็นเลขคี่: +วงวนด้านล่างใช้ `continue` เพื่อแสดงผลแค่ค่าคี่เท่านั้น: ```js run no-beautify for (let i = 0; i < 10; i++) { - // ถ้า true ข้ามส่วนที่เหลือของ body ไป + // ถ้าเป็นจริง ให้ข้ามส่วนที่เหลือในรอบนี้ *!*if (i % 2 == 0) continue;*/!* alert(i); // 1, แล้วก็ 3, 5, 7, 9 } ``` -สำหรับค่า `i` ที่เป็นเลขคู่ คำสั่ง `continue` จะหยุดการทำงานของ body และส่งต่อการควบคุมไปยัง iteration ถัดไปของ `for` (ด้วยเลขตัวถัดไป) ดังนั้น `alert` จะถูกเรียกใช้เฉพาะสำหรับเลขคี่ +สำหรับค่า `i` ที่เป็นเลขคู่ คำสั่ง `continue` จะหยุดการทำงานในรอบปัจจุบันแล้วส่งการควบคุมไปเริ่มรอบถัดไปของ `for` (ด้วยตัวเลขถัดไป) ดังนั้น `alert` จะถูกเรียกเฉพาะสำหรับค่าคี่เท่านั้น -````smart header="`continue` ช่วยลดการซ้อนกันของโค้ด" -Loop ที่แสดงแต่เลขคี่สามารถเขียนได้แบบนี้: +````smart header="คำสั่ง `continue` ช่วยลดการซ้อนโค้ด" +วงวนที่แสดงค่าคี่อาจเขียนได้แบบนี้: ```js run for (let i = 0; i < 10; i++) { @@ -272,64 +273,64 @@ for (let i = 0; i < 10; i++) { if (i % 2) { alert( i ); } - + } ``` -ในแง่ของเทคนิค สิ่งนี้เหมือนกับตัวอย่างด้านบน แน่นอน เราสามารถห่อโค้ดใส่บล็อก `if` แทนการใช้ `continue` ได้ +ในแง่เทคนิค มันจะเหมือนกับตัวอย่างข้างบน แน่นอนว่าเราเพียงแค่ใส่โค้ดไว้ในบล็อก `if` แทนการใช้ `continue` ก็ได้ -แต่ผลข้างเคียงคือ มันจะสร้างการซ้อนกันของโค้ดขึ้นมาอีกชั้นหนึ่ง (การเรียก `alert` อยู่ในปีกกาหยัก) ถ้าโค้ดใน `if` ยาวกว่าสองสามบรรทัด มันอาจทำให้โค้ดอ่านยากขึ้น +แต่มันก่อให้เกิดผลข้างเคียงคือเพิ่มระดับการซ้อนโค้ดอีกชั้น (เรียก `alert` ภายในปีกกาหลังเงื่อนไข) ถ้าโค้ดใน `if` ยาวกว่าสองสามบรรทัด มันอาจลดความสามารถในการอ่านโค้ดโดยรวม ```` -````warn header="ไม่มี `break/continue` อยู่ทางขวาของ '?'" -โปรดทราบว่า syntax constructs ที่ไม่ใช่ expressions ไม่สามารถใช้กับตัวดำเนินการ ternary `?` ได้ โดยเฉพาะคำสั่งอย่าง `break/continue` จะไม่อนุญาตให้ใช้ได้ +````warn header="ไม่มี `break/continue` ทางขวาของเครื่องหมาย '?'" +โปรดทราบว่าโครงสร้างทางไวยากรณ์ที่ไม่ใช่นิพจน์ ไม่สามารถใช้กับตัวดำเนินการ ternary `?` ได้ โดยเฉพาะอย่างยิ่ง คำสั่งอย่างเช่น `break/continue` จะใช้ไม่ได้ -ตัวอย่างเช่น ถ้าเราเอาโค้ดนี้: +ตัวอย่างเช่น ถ้าเรามีโค้ดแบบนี้: ```js if (i > 5) { alert(i); } else { continue; -} +} ``` ...แล้วเขียนใหม่โดยใช้เครื่องหมายคำถาม: ```js no-beautify -(i > 5) ? alert(i) : *!*continue*/!*; // ไม่อนุญาต continue ให้ใช้ที่นี่ +(i > 5) ? alert(i) : *!*continue*/!*; // continue ใช้ที่นี่ไม่ได้ ``` -...มันจะไม่ทำงาน: จะเป็น syntax error +...มันจะไม่ทำงาน: จะเกิด syntax error -นี่เป็นอีกเหตุผลหนึ่งที่ไม่ควรใช้ตัวดำเนินการ `?` แทน `if` +นี่เป็นอีกเหตุผลที่ไม่ควรใช้ตัวดำเนินการ `?` แทน `if` ```` -## Labels สำหรับ break/continue +## ป้ายกำกับสำหรับ break/continue -บางครั้งเราต้องการ break ออกจาก nested loops หลายชั้นในครั้งเดียว +บางครั้งเราต้องการออกจากลูปที่ซ้อนกันหลายชั้นในครั้งเดียว -ตัวอย่างเช่น ในโค้ดด้านล่าง เราจะวน loop บน `i` และ `j` เพื่อรับค่าพิกัด `(i, j)` จาก `(0,0)` ถึง `(2,2)`: +ตัวอย่างเช่น ในโค้ดด้านล่าง เราวนลูปด้วย `i` และ `j` พร้อมถามพิกัด `(i, j)` ตั้งแต่ `(0,0)` ถึง `(2,2)`: ```js run no-beautify for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { - let input = prompt(`Value at coords (${i},${j})`, ''); + let input = prompt(`ค่าที่พิกัด (${i},${j})`, ''); - // ถ้าเราต้องการออกจากนี่ไปที่ Done (ด้านล่าง) ล่ะ? + // จะทำอย่างไรถ้าเราต้องการออกจากที่นี่ไปยัง Done (ด้านล่าง)? } } alert('Done!'); ``` -เราต้องการหยุดกระบวนการนี้ได้ถ้าผู้ใช้ยกเลิกการป้อนค่า +เราต้องการวิธีหยุดกระบวนการ หากผู้ใช้ยกเลิกการป้อนข้อมูล -`break` ปกติหลัง `input` จะออกจาก inner loop เท่านั้น มันไม่พอ - เราต้องใช้ labels! +คำสั่ง `break` ปกติหลัง `input` จะออกจากลูป inner เท่านั้น ซึ่งยังไม่เพียงพอ -- ตอนนี้ป้ายกำกับมาช่วยเราได้! -*Label* คือ identifier ที่ตามด้วยเครื่องหมายทวิภาคก่อน loop: +*ป้ายกำกับ* คือตัวระบุที่มีเครื่องหมายทวิภาคนำหน้าลูป: ```js labelName: for (...) { @@ -337,74 +338,74 @@ labelName: for (...) { } ``` -คำสั่ง `break ` ในตัวอย่างด้านล่างจะหยุด loop แล้วออกไปที่ label: +คำสั่ง `break ` ในลูปด้านล่างจะออกไปยังป้ายกำกับ: ```js run no-beautify *!*outer:*/!* for (let i = 0; i < 3; i++) { for (let j = 0; j < 3; j++) { - let input = prompt(`Value at coords (${i},${j})`, ''); + let input = prompt(`ค่าที่พิกัด (${i},${j})`, ''); - // ถ้าใส่สตริงว่าง หรือกด cancel, ให้ออกจากทั้งสอง loops + // ถ้า string ว่างหรือยกเลิก จะออกจากลูปทั้งสอง if (!input) *!*break outer*/!*; // (*) - // ทำบางอย่างกับค่าที่ได้... + // ทำอะไรบางอย่างกับค่า... } } alert('Done!'); ``` -ในโค้ดด้านบน `break outer` จะมองหา label ชื่อ `outer` ข้างบนและหยุดการทำงานของ loop นั้น +ในโค้ดข้างบน `break outer` จะค้นหาป้ายกำกับชื่อ `outer` ขึ้นไปและออกจากลูปนั้น -เพราะฉะนั้นการทำงานจะกระโดดจาก `(*)` ไปที่ `alert('Done!')` เลย +ดังนั้นการควบคุมจะข้ามจาก `(*)` ไปยัง `alert('Done!')` ทันที -เราสามารถย้าย label ไปอยู่บนบรรทัดแยกต่างหากได้: +เราสามารถย้ายป้ายกำกับไปอยู่บนบรรทัดแยกต่างหากก็ได้: ```js no-beautify outer: -for (let i = 0; i < 3; i++) { ... } +for (let i = 0; i < 3; i++) { ... } ``` -คำสั่ง `continue` ก็สามารถใช้กับ label ได้ในแบบเดียวกัน ในกรณีนี้ การทำงานของโค้ดจะกระโดดไปที่การเริ่ม iteration ถัดไปของ loop ที่มี label +คำสั่ง `continue` ก็ใช้กับป้ายกำกับได้เช่นกัน ในกรณีนี้ การทำงานของโค้ดจะข้ามไปยังรอบถัดไปของลูปที่ติดป้ายกำกับ -````warn header="Labels ไม่อนุญาตให้ \"กระโดด\" ไปที่ไหนก็ได้" -Labels ไม่อนุญาตให้เรากระโดดไปยังจุดใด ๆ ในโค้ดได้อย่างอิสระ +````warn header="ป้ายกำกับไม่อนุญาตให้ \"กระโดด\" ไปที่ไหนก็ได้" +ป้ายกำกับไม่อนุญาตให้เรากระโดดไปยังตำแหน่งใดๆ ในโค้ดตามใจชอบ -ตัวอย่างเช่น มันไม่สามารถทำแบบนี้ได้: +เช่น ไม่สามารถทำแบบนี้: ```js -break label; // กระโดดไปยัง label ด้านล่าง (ไม่ทำงาน) +break label; // กระโดดไปที่ป้ายกำกับด้านล่าง (ทำไม่ได้) -label: for (...) +label: for (...) ``` -คำสั่ง `break` ต้องอยู่ภายใน code block เท่านั้น ในทางเทคนิค label สามารถใส่หน้า code block ใด ๆ ก็ได้ เช่น: +คำสั่ง `break` ต้องอยู่ในบล็อกโค้ด โดยทั่วไปแล้ว บล็อกโค้ดใดๆ ที่มีป้ายกำกับก็ใช้ได้ เช่น: ```js label: { // ... - break label; // ทำงาน - // ... + break label; // ใช้ได้ + // ... } ``` -...แม้ว่า 99.9% ของครั้ง `break` จะถูกใช้ข้างใน loops เหมือนในตัวอย่างที่เราเห็นด้านบน +...ถึงแม้ว่า 99.9% ของเวลา `break` จะใช้ในลูป ตามที่เราเห็นในตัวอย่างข้างบน -`continue` ก็ใช้ได้เฉพาะข้างใน loop เท่านั้น +`continue` ใช้ได้เฉพาะข้างในลูปเท่านั้น ```` ## สรุป -เราได้พูดถึง loop 3 แบบ: +เราได้เรียนรู้ลูป 3 ประเภท: -- `while` -- เงื่อนไขจะถูกตรวจสอบก่อนเริ่มแต่ละ iteration -- `do..while` -- เงื่อนไขจะถูกตรวจสอบหลังจบแต่ละ iteration -- `for (;;)` -- เงื่อนไขจะถูกตรวจสอบก่อนเริ่มแต่ละ iteration และสามารถกำหนดการตั้งค่าเพิ่มเติมได้ +- `while` -- ตรวจสอบเงื่อนไขก่อนแต่ละรอบ +- `do..while` -- ตรวจสอบเงื่อนไขหลังแต่ละรอบ +- `for (;;)` -- ตรวจสอบเงื่อนไขก่อนแต่ละรอบ พร้อมตั้งค่าเพิ่มเติมได้ -ในการสร้าง "infinite" loop โดยทั่วไปจะใช้ `while(true)` การสร้างแบบนี้ เหมือนกับ loop แบบอื่น ๆ สามารถหยุดได้ด้วยคำสั่ง `break` +โดยทั่วไป เพื่อสร้างลูป "ไม่มีที่สิ้นสุด" จะใช้ `while(true)` ลูปแบบนี้เหมือนลูปอื่นๆ คือสามารถหยุดได้ด้วยคำสั่ง `break` -ถ้าเราไม่ต้องการทำอะไรใน iteration ปัจจุบัน และต้องการข้ามไปที่รอบถัดไป เราสามารถใช้คำสั่ง `continue` +ถ้าเราไม่ต้องการทำอะไรในรอบปัจจุบัน และต้องการข้ามไปทำรอบถัดไป เราสามารถใช้คำสั่ง `continue` -`break/continue` รองรับการใส่ label ไว้ข้างหน้า loop label เป็นวิธีเดียวที่ `break/continue` จะสามารถออกจาก nested loop ได้และไปยัง outer loop +`break/continue` รองรับป้ายกำกับไว้ข้างหน้าลูป ป้ายกำกับเป็นวิธีเดียวที่ `break/continue` จะออกจากลูปที่ซ้อนเพื่อไปยังลูปด้านนอกได้ \ No newline at end of file