1. דף הבית
  2. קורסים אונליין
  3. קורס Javascript אונליין
  4. לולאות while, continue, break ב-JavaScript

לולאות while, continue, break ב-JavaScript

לולאת while מאפשרת ביצוע קטע קוד באופן חזרתי, כל עוד תנאי הלולאה מתקיים. במדריך זה נסקור את לולאת while ולולאת do .. while, נכיר את ההצהרות break ו-continue, נלמד לעבוד עם לולאות while מקוננות ועוד.
לולאות while ב-JS

לולאת while בג'אווה סקריפט

ב-JavaScript, לולאת while מספקת דרך לבצע שוב ושוב בלוק קוד, כל עוד תנאי שצוין מתקיים. לולאות while שימושיות כאשר מספר האיטרציות אינו ידוע מראש ותלוי בתנאים דינמיים.

להלן התחביר הבסיסי של הלולאה:

while (condition) {
    // code block to be executed
}

כל עוד מתקיים התנאי condition, בלוק הקוד יבוצע שוב. בדיקת התנאי נעשית לפני ביצוע בלוק הקוד, ולכן, יתכן מצב שבו התנאי אינו מתקיים כבר בהתחלה ובלוק הקוד לא ירוץ אפילו פעם אחת.

דוגמה:

let count = 0;
while (count < 5) {
    console.log(count);
    count++;
}
// Output:
// 0
// 1
// 2
// 3
// 4

בדוגמה זו, המשתנה count מאותחל לערך 0. בתחילת כל איטרציה בלולאה, נבדק האם count < 5. אם התנאי מתקיים, מבצעים את בלוק הקוד, שבו מודפס ערך המשתנה count בקונסול וכן ערך המשתנה גדל ב-1. אם התנאי אינו מתקיים, הלולאה מסתיימת.

 

דוגמה נוספת:

let input;
while (input !== 'yes') {
    input = prompt('Do you want to continue? (yes/no)');
}
console.log('User agreed to continue.');

בדוגמה זו, מוגדר המשתנה input. כל עוד ערך המשתנה input אינו המחרוזת yes, מבוצע בלוק הקוד. בבלוק הקוד אנו מבקשים מהמשתמש להכניס ערך האם הוא מעוניין להמשיך. אם המשתמש יכניס את המחרוזת yes, הלולאה תסתיים.

מקרי קצה בלולאות while והטיפול מהם

בעיה אפשרית בשימוש בלולאת while הוא מקרה בו הלולאה אינה רצה כלל. דבר זה יכול לקרות אם התנאי שבלולאה אינו מתקיים עוד בבדיקה הראשונה שלו.

דוגמה:

let count = 10;
while (count < 5) {
    console.log(count);
    count++;
}
// This loop will never run

בדוגמה זו, במבט ראשון על הלולאה, נראה כאילו היא צריכה לרוץ 5 פעמים, כיוון שהלולאה מגדילה בכל פעם את ערך המשתנה count, ורצה כל עוד הערך קטן מ-5. עם זאת, הלולאה לא תרוץ כלל. זאת מכיוון שלפני ביצוע הלולאה, עוד בשלב אתחול המשתנה count, קבענו את ערך המשתנה count להיות 10, ולכן תנאי הלולאה אינו מתקיים עוד בהתחלה.

 

בעיה נוספת שעלולה לקרות בשימוש בלולאות while, נפוצה הרבה יותר, היא בעיה של לולאה אינסופית. דבר זה יכול לקרות אם התנאי בלולאה מתקיים כל הזמן.

דוגמה:

let count = 0;
while (count < 5) {
    console.log(count);
    // count is never incremented
}

בדוגמה זו, שכחנו להגדיל את ערך המשתנה count בכל איטרציה. לכן, ערך המשתנה ישאר תמיד 0, תנאי הלולאה יתקיים תמיד והלולאה תרוץ ללא הפסקה.

 

טיפים להימנעות מלולאה שלא רצה ומלולאה אינסופית:

  1. ודא ערך תנאי התחלתי - ודא שהתנאי מתקיים בטרם הכניסה לקוד הלולאה, כדי למנוע מצב שהלולאה לא תרוץ כלל.
  2. ודא שינויים בתנאי הלולאה - ודא שהתנאי יהפוך בסופו של דבר ל-false, כלומר יחדל מלהתקיים, על ידי עדכון משתנים המעורבים בתנאי הלולאה.
  3. איתור באגים - בדוק מצבים שונים של הלולאה בנקודות עצירה שונות בקוד. תוכל להעזר בהדפסת ערכים לקונסול לשם כך. כך תעקוב אחר ביצוע הלולאה ותבין אם היא מתנהגת כמצופה.
  4. הגבלת איטרציות - במקרה שיש חשש שהלולאה תהיה אינסופית, יישם הגנה על ידי הגבלת מספר האיטרציות אם אינך בטוח לגבי מצב הלולאה. אפשר לעשות זאת בקלות על ידי קביעת אינדקס שמונה את כמות האיטרציות ויציאה מהלולאה אם הוא מגיע לערך גדול כלשהו.

לולאת do .. while

לולאת do .. while היא גירסה מעט שונה ללולאת while הסטנדרטית. בגירסה זו, התנאי של הלולאה נבדק בסוף האיטרציה במקום בתחילתה. באופן הזה, מובטח כי הלולאה תרוץ לפחות פעם אחת, דבר שאינו מובטח בלולאת while סטנדרטית.

להלן התחביר הבסיסי של הלולאה:

do {
    // code block to be executed
} while (condition);

 

דוגמה:

let count = 0;
do {
    console.log(count);
    count++;
} while (count < 5);
// Output:
// 0
// 1
// 2
// 3
// 4

בדוגמה זו, ניתן לראות כי בבלוק הלולאה מודפס ערך המשתנה count ולאחר מכן מתבצעת הגדלה של ערך המשתנה ב-1. בסיום כל איטרציה, נבדק התנאי count < 5 ואם הוא מתקיים ממשיכים לאיטרציה נוספת. נשים לב כי הלולאה תרוץ פעם אחת לפחות, בלי קשר לערך ההתחלתי של count. גם אם היינו מאתחלים את המשתנה count בערך 1000, הלולאה היתה רצה פעם אחת ומסתיימת אחרי האיטרציה הראשונה.

לולאות while מקוננות

דרך עבודה נפוצה, היא קינון לולאות while, כלומר, להכניס לולאה בתוך לולאה.

דוגמה:

let i = 0;
while (i < 3) {
    let j = 0;
    while (j < 3) {
        console.log(`i = ${i}, j = ${j}`);
        j++;
    }
    i++;
}
// Output:
// i = 0, j = 0
// i = 0, j = 1
// i = 0, j = 2
// i = 1, j = 0
// i = 1, j = 1
// i = 1, j = 2
// i = 2, j = 0
// i = 2, j = 1
// i = 2, j = 2

בדוגמה זו, ביצענו קינון ב-2 רמות עומק, כלומר, לולאה בתוך לולאה. הלולאה החיצונית, זו שהאינדקס שלה הוא i, רצה 3 פעמים. בכל איטרציה של הלולאה החיצונית, הלולאה הפנימית, זו שהאינדקס שלה הוא j, רצה 3 פעמים. בסה"כ, הלולאה הפנימית רצה 9 פעמים.

 

ניתן לקנן ביותר מ-2 רמות עומק. כמו כן, ניתן לשלב כמה סוגי לולאות בקינון. נדגים עכשיו קינון של 3 סוגי לולאות (לולאת for, לולאת while ולולאת do .. while) ב-3 רמות עומק.

דוגמה:

// Initialize a 3-dimensional array
let cube = [
    [   // First layer (z = 0)
        [1, 2, 3],    // Row 0
        [4, 5, 6],    // Row 1
        [7, 8, 9]     // Row 2
    ],
    [   // Second layer (z = 1)
        [10, 11, 12], // Row 0
        [13, 14, 15], // Row 1
        [16, 17, 18]  // Row 2
    ],
    [   // Third layer (z = 2)
        [19, 20, 21], // Row 0
        [22, 23, 24], // Row 1
        [25, 26, 27]  // Row 2
    ]
];

// Iterate over the 3-dimensional array
let z = 0; // While loop for the z-dimension
while (z < cube.length) {
    console.log(`Layer z = ${z}`);
    
    let y = 0; // Do-while loop for the y-dimension
    do {
        console.log(`  Row y = ${y}`);
        
        // For loop for the x-dimension
        for (let x = 0; x < cube[z][y].length; x++) {
            console.log(`    cube[${z}][${y}][${x}] = ${cube[z][y][x]}`);
        }
        
        y++;
    } while (y < cube[z].length);
    
    z++;
}

// Output:
// Layer z = 0
//   Row y = 0
//     cube[0][0][0] = 1
//     cube[0][0][1] = 2
//     cube[0][0][2] = 3
//   Row y = 1
//     cube[0][1][0] = 4
//     cube[0][1][1] = 5
//     cube[0][1][2] = 6
//   Row y = 2
//     cube[0][2][0] = 7
//     cube[0][2][1] = 8
//     cube[0][2][2] = 9
// Layer z = 1
//   Row y = 0
//     cube[1][0][0] = 10
//     cube[1][0][1] = 11
//     cube[1][0][2] = 12
//   Row y = 1
//     cube[1][1][0] = 13
//     cube[1][1][1] = 14
//     cube[1][1][2] = 15
//   Row y = 2
//     cube[1][2][0] = 16
//     cube[1][2][1] = 17
//     cube[1][2][2] = 18
// Layer z = 2
//   Row y = 0
//     cube[2][0][0] = 19
//     cube[2][0][1] = 20
//     cube[2][0][2] = 21
//   Row y = 1
//     cube[2][1][0] = 22
//     cube[2][1][1] = 23
//     cube[2][1][2] = 24
//   Row y = 2
//     cube[2][2][0] = 25
//     cube[2][2][1] = 26
//     cube[2][2][2] = 27

בדוגמה זו, הגדרנו משתנה cube שהוא מערך עם 3 מימדים. בדוגמה אנו סורקים את המשתנה באמצעות שילוב של 3 סוגי הלולאות: for, while, do .. while וזאת באמצעות 3 רמות עומק של קינון. הלולאה החיצונית היא לולאת while, בתוכה לולאת do .. while ופנימית יותר לולאת for.

דוגמה זו היא קצת מלאכותית, ונועדה רק להמחשת שילוב הלולאות וקינון לולאות. בעולם האמיתי נשתדל לשמור על מבנה קוד קריא יותר, כאשר את הקוד הזה ניתן היה לכתוב בצורה קריאה הרבה יותר באמצעות 3 לולאות for מקוננות.

הצהרות break ו-continue בלולאות while

כמו בלולאות for, גם בלולאות while ו- do .. while ניתן להשתמש בהצהרות break ו-continue.

הצהרת break יוצאת מלולאת ה-while מיד.

דוגמה:

let count = 0;
while (count < 10) {
    if (count === 5) {
        break;
    }
    console.log(count);
    count++;
}
// Output:
// 0
// 1
// 2
// 3
// 4

בדוגמה זו, הלולאה תרוץ כל עוד התנאי count < 10 מתקיים. בתחילת כל איטרציה, נבדק האם count === 5, כלומר המשתנה count הוא מטיפוס מספרי וזהה לערך 5. אם התנאי הזה מתקיים, הלולאה תסתיים מיד.

 

הצהרת continue מסיימת את האיטרציה הנוכחית של לולאת ה-while וממשיכה לאיטרציה הבאה.

דוגמה:

let count = 0;
while (count < 10) {
    count++;
    if (count % 2 === 0) {
        continue;
    }
    console.log(count);
}
// Output:
// 1
// 3
// 5
// 7
// 9

בדוגמה זו, הלולאה רצה כל עוד מתקיים התנאי count < 10. בתחילת כל איטרציה מגדילים את המשתנה count ב-1, ולאחר מכן בודקים את התנאי count % 2 === 0, כלומר, האם המשתנה count מתחלק ב-2 ללא שארית (או במילים אחרות: האם count עם ערך זוגי). אם התנאי מתקיים, מדלגים לאיטרציה הבא. ניתן לראות כי קטע הקוד מדפיס בקונסול את ערכי count האי זוגיים בלבד, כיוון שבכל פעם ש-count עם ערך זוגי מדלגים לאיטרציה הבאה ולא מגיעים לשורת ההדפסה.

לולאת while עם תווית

כפי שראינו עבור לולאות for, גם בלולאות while ניתן לקבוע תווית שם ללולאה, ואז להתייחס אליה כשרוצים לבצע break או continue.

 

הצהרת break עם תווית, מבצעת יציאה מהלולאה שתווית זו שייכת לה.

דוגמה:

// Initialize a 2-dimensional array
let matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
];

let target = 5; // Value to search for
let found = false;

// Label for the outer loop
outerLoop:
while (!found) {
    let i = 0;
    while (i < matrix.length) {
        let j = 0;
        while (j < matrix[i].length) {
            if (matrix[i][j] === target) {
                console.log(`Found target ${target} at matrix[${i}][${j}]`);
                found = true;
                break outerLoop; // Break out of both loops
            }
            j++;
        }
        i++;
    }
}

if (!found) {
    console.log(`Target ${target} not found in the matrix.`);
}

// Output:
// Found target 5 at matrix[1][1]

דוגמה זו מדגימה חיפוש של מספר נתון במערך דו מימדי. המערך שלנו הוא matrix ואנו מחפשים את המספר target בתוכו. אנו עושים זאת באמצעות 2 לולאות while מקוננות, כאשר קבענו ללולאה החיצונית את התווית outerLoop. הלולאות עוברות איבר-איבר במערך ובכל איטרציה בודקים את קיום התנאי matrix[i][j] === target, כלומר, האם ערך האיבר אותו בודקים באיטרציה הנוכחית שווה לערך של target. אם התנאי מתקיים, מדפיסים בקונסול הודעה עם המיקום במערך בו נמצא האיבר ויוצאים מיד מהלולאה החיצונית בהצהרת break outerLoop. אם התנאי אינו מתקיים, ממשיכים בבדיקות עד שכל המערך נסרק. אם האיבר לא נמצא כלל בסיום הסריקה, מודפסת בקונסול ההודעה שהאיבר לא נמצא.

נשים לב שהיציאה באמצעות ההצהרה break outerLoop יוצאת מהלולאה החיצונית ומסיימת לחלוטין את הסריקה. אם היינו מחליפים את ההצהרה הזו בהצהרת break ללא תווית, היציאה היתה רק מהלולאה הפנימית והיינו ממשיכים בסריקה אחר target, למרות שהוא כבר נמצא.

 

הצהרת continue עם תווית, מדלגת לאיטרציה הבאה בלולאה שתווית זו שייכת לה.

דוגמה:

// Initialize a 2-dimensional array
let matrix = [
    [1, 2, 3],
    [4, -5, 6],
    [7, 8, 9]
];

let i = 0;
// Label for the outer loop
outerLoop:
while (i < matrix.length) {
	console.log(`Processing row ${i}`);
	
	let j = 0;
	while (j < matrix[i].length) {
		if (matrix[i][j] < 0) { // If an element is negative
			console.log(`  Found negative value at matrix[${i}][${j}] = ${matrix[i][j]}. Skipping row ${i}.`);
			i++; // Move to the next row
			continue outerLoop; // Skip the rest of this row and continue with the next row
		}
		console.log(`  Processing element matrix[${i}][${j}] = ${matrix[i][j]}`);
		j++;
	}
	
	i++;
	if (i >= matrix.length) {
		break outerLoop; // Break out of the outer loop when all rows are processed
	}
}


// Output:
// Processing row 0
//   Processing element matrix[0][0] = 1
//   Processing element matrix[0][1] = 2
//   Processing element matrix[0][2] = 3
// Processing row 1
//   Processing element matrix[1][0] = 4
//   Found negative value at matrix[1][1] = -5. Skipping row 1.
// Processing row 2
//   Processing element matrix[2][0] = 7
//   Processing element matrix[2][1] = 8
//   Processing element matrix[2][2] = 9

בדוגמה זו, אנו סורקים את המערך הדו מימדי matrix ומחפשים בכל שורה במערך את המספר השלילי הראשון שנמצא. ניתן לראות כי בתוך הלולאה הפנימית, נבדק התנאי matrix[i][j] < 0, כלומר, האם האיבר אותו בודקים באיטרציה הנוכחית הוא מספר שלילי. אם התנאי מתקיים, מדלגים באמצעות הצהרת continue outerLoop לאיטרציה הבאה בלולאה החיצונית, ולמעשה מסיימים את כל סריקת המספרים השליליים בשורה הנוכחית במערך.

מתי להשתמש בכל סוג של לולאה?

נתין להמיר כל קוד שעושה שימוש באחת מהלולאות הנפוצות (for, while, do .. while) לקוד חלופי שעושה שימוש בלולאה מסוג אחר.

עם זאת, יש מצבים שונים בהם נעדיף להשתמש בכל לולאה. להלן כמה טיפים בנושא:

  • בחר בלולאת while במקרים בהם מספר האיטרציות אינו ידוע מראש ויש צורך בגמישות רבה יותר בניהול מצב הלולאה.
  • בחר בלולאת for במקרים בהם מספר האיטרציות ידוע ובמקרים בהם סורקים בצורה סדרתית מערכים ואוספים מסוגים שונים.
  • בחר בלולאת do .. while במקרה בו יש צורך שגוף הלולאה יבוצע לפחות פעם אחת, ללא קשר לתנאי.

 

נשים לב כי לולאת for משלבת בהגדרתה אתחול, תנאי והגדלה, בניגוד ללולאות while או do .. while שבהן קיים רק תנאי בצורה מובנית. אם יש צורך באתחול ובהגדלה בלולאות while ו-do .. while, אלו יכולים להעשות לפני קוד הלולאה או בתוך גוף הלולאה.

לכן, משיקולי קריאות, במקרים בהם יש צורך באתחול ובהגדלה, נעדיף במידת האפשר שימוש בלולאת for.

דוגמה:

let i = 0;
while (i < 5) {
    console.log(i);
    i++;
}

for (let i = 0; i < 5; i++) {
    console.log(i);
}

בדוגמה זו, אנו רואים 2 לולאות, הראשונה לולאת while והשניה לולאת for. שתי הלולאות שקולות ועושות בדיוק אותו הדבר: הדפסה של המספרים 0 עד 4 בקונסול. בלולאת ה-while ביצענו את אתחול האינדקס i לפני הגדרת הלולאה, ואת הגדלת המשתנה i בגוף הלולאה.

טיפים לשימוש בלולאות while בג'אווה סקריפט

להלן טיפים לשימוש נכון יותר בלולאות while:

  • אתחול - ודא שהמשתנים המשמשים בתנאי מאותחלים כראוי לפני שהלולאה מתחילה.
  • תנאי - ודא שהתנאי יחדל מלהתקיים בסופו של דבר, כדי למנוע לולאות אינסופיות.
  • עדכונים - ודא עידכון של המשתנים המעורבים בתנאי הלולאה, כדי להתקדם לקראת סיום הלולאה.
  • איתור באגים - ניתן להשתמש בהדפסה לקונסול, כדי לנפות באגים ולהבין את זרימת הלולאה, במיוחד בתנאים מורכבים.
  • ביצועים - מומלץ לקחת בחשבון שיקולי ביצועים בעת שימוש בלולאות (ובמיוחד שימוש בלולאות מקוננות), מכיוון שהן עלולות להוביל לתקורה חישובית משמעותית ולזמני ריצה ארוכים. חישובים שניתן לעשותם בטרם הכניסה ללולאה עדיפים מחזרה על חישובים בכל איטרציה.
הוספת תגובה
אנו משתמשים בעוגיות על מנת לשפר את חווית המשתמש באתר. מדיניות הפרטיותאני מסכים