הצהרת throw בג'אווה סקריפט משמשת ליצירת שגיאות מותאמות אישית. באמצעות throw ניתן ליצור exceptions ולטפל בהן באמצעות הצהרת try…catch, דבר המאפשר ניהול יעיל יותר וטיפול בשגיאות בצורה מבוקרת.
תחביר בסיסי – Syntax
התחביר הבסיסי של הצהרת throw נראה כך:
throw expression;
אל תשברו שורה בין מילת המפתח
throwלביטוי. מנגנון ה-ASI (Automatic Semicolon Insertion) של JavaScript יתייחס לשבירת השורה כסוף ההצהרה, מה שיגרום ל-throw;שהיא שגיאת תחביר.
אותו expression יכול להיות כל ביטוי תקני ב-JavaScript, אבל תמיד כדאי לזרוק אובייקט Error (או תת-מחלקה שלו). זריקת מחרוזות או מספרים אפשרית טכנית אך מונעת גישה ל-stack trace ומקשה על ניפוי שגיאות.
תמיד השתמשו ב-throw new Error('message') או תת-מחלקת Error מותאמת. זריקת מחרוזת פשוטה כמו throw 'something went wrong' לא מייצרת stack trace ולא ניתנת ללכידה לפי סוג.
דוגמה לשימוש ב-throw
הנה קוד JavaScript המדגים את השימוש בהצהרת throw:
function divide(a, b) {
if (b === 0) {
throw new Error('Division by zero is not allowed.');
}
return a / b;
}
try {
console.log(divide(4, 2)); // Output: 2
console.log(divide(4, 0)); // Throws error
} catch (error) {
console.error(error.message); // Output: Division by zero is not allowed.
}
בדוגמה זו, אם הערך b הוא אפס, נזרקת שגיאה עם הודעה מותאמת אישית. הבלוק try…catch משמש לטיפול בשגיאה ולהצגת ההודעה.
שימוש ב-throw עם שגיאות מותאמות אישית
ניתן ליצור אובייקט שגיאה מותאם אישית על ידי הרחבת מחלקת ה- Error המובנית. פעולה זו מאפשרת הגדרת סוגי שגיאות ספציפיים לאפליקציה שלכם:
class ValidationError extends Error {
constructor(message) {
super(message);
this.name = 'ValidationError';
}
}
function validateAge(age) {
if (age < 0 || age > 120) {
throw new ValidationError('Invalid age value.');
}
return true;
}
try {
validateAge(150); // Throws ValidationError
} catch (error) {
if (error instanceof ValidationError) {
console.error(error.message); // Output: Invalid age value.
} else {
console.error('Unknown error:', error);
}
}
״השלכת״ שגיאות מחדש – Re-throwing Errors
במקרים מסוימים, תרצו לטפל בשגיאה באופן חלקי ואז להשליך אותה מחדש כדי שבלוק try...catch אחר יוכל לטפל בה:
function parseJSON(jsonString) {
try {
return JSON.parse(jsonString);
} catch (error) {
if (error instanceof SyntaxError) {
console.error('JSON parsing error:', error.message);
throw error; // Re-throw the error
} else {
throw new Error('Unknown error');
}
}
}
try {
parseJSON('invalid JSON');
} catch (error) {
console.error('Caught an error:', error.message);
}
שרשור שגיאות עם cause
ES2022 הציגה את המאפיין cause, שמאפשר לצרף את השגיאה המקורית בעת זריקת שגיאה חדשה. כך נשמר שרשור השגיאות המלא מבלי לאבד הקשר:
async function fetchUser(id) {
try {
const response = await fetch(`/api/users/${id}`);
if (!response.ok) {
throw new Error(`HTTP ${response.status}`);
}
return await response.json();
} catch (error) {
throw new Error('Failed to fetch user', { cause: error });
}
}
try {
await fetchUser(42);
} catch (error) {
console.error(error.message); // "Failed to fetch user"
console.error(error.cause.message); // "HTTP 404" (the original error)
}
המאפיין cause נתמך בכל הדפדפנים המודרניים וב-Node.js 16.9+.
שיטות עבודה מומלצות
להלן שיטות עבודה מומלצות לשימוש יעיל בהצהרת throw:
- תמיד זרקו אובייקטי Error: לעולם אל תזרקו מחרוזות או מספרים. אובייקטי Error מספקים
.message,.name,.stackואופציונלית.cause– כולם חיוניים לניפוי שגיאות. - כתבו הודעות תיאוריות: כתבו הודעות שגיאה שמסבירות מה השתבש, וכשאפשר, כללו את הערך הלא תקין או ההקשר.
- צרו סוגי שגיאות מותאמים: הגדירו תת-מחלקות Error עבור תרחישים ספציפיים לתחום. כך הקוד הקורא יכול להשתמש ב-
instanceofכדי לטפל בשגיאות שונות בצורה שונה. - השתמשו ב-try…catch: תמיד טפלו בשגיאות שנזרקו באמצעות בלוקי
try...catchכדי למנוע קריסת האפליקציה. - השליכו מחדש עם הקשר: בעת לכידה והשלכה מחדש, השתמשו באפשרות
causeכדי לשמר את השגיאה המקורית. - אל תלכדו בצורה גורפת: הימנעו מלכידת
Errorברמה העליונה והתעלמות שקטה ממנו. תעדו את השגיאה או טפלו בה בצורה משמעותית.
שאלות נפוצות
שאלות נפוצות על הצהרת throw ב-JavaScript:
throw 'error' לא מייצרת stack trace, אין לה מאפיין .name, ואין תמיכה ב-.cause. תמיד זרקו new Error('message') או תת-מחלקת Error מותאמת.return יוצא מפונקציה ומעביר ערך לקוד הקורא. throw יוצא מפונקציה וקופץ לבלוק catch הקרוב ביותר ב-call stack. אם אין catch, התוכנית קורסת. השתמשו ב-throw עבור מצבים חריגים שהקוד הקורא חייב לטפל בהם, לא עבור זרימת שליטה רגילה.async, throw דוחה את ה-Promise המוחזר. הקוד הקורא יכול ללכוד את השגיאה עם try...catch (בתוך פונקציית async אחרת) או עם .catch() על ה-Promise. ההתנהגות שקולה לקריאה ל-Promise.reject(new Error('message')).ValidationError עשוי להפעיל הודעה למשתמש, בעוד ש-HttpError עשוי להפעיל ניסיון חוזר. אם Error גנרי עם הודעה תיאורית מספיק, אין צורך ליצור מחלקה מותאמת.cause (ES2022) מאפשר לשרשר שגיאות על ידי צירוף השגיאה המקורית לשגיאה חדשה: throw new Error('High-level message', { cause: originalError }). כך נשמר ההקשר המלא של השגיאה, מה שמקל על ניפוי שגיאות כשהן נלכדות ונזרקות מחדש במספר שכבות.סיכום
הצהרת throw מאפשרת ליצור שגיאות מותאמות שמתפשטות במעלה ה-call stack עד שבלוק catch מטפל בהן. תמיד זרקו אובייקטי Error או תת-מחלקות מותאמות – לעולם לא מחרוזות או מספרים פשוטים.
הרחיבו את מחלקת Error כדי ליצור סוגי שגיאות ספציפיים לתחום שהקוד הקורא יכול לזהות באמצעות instanceof. השתמשו במאפיין cause (ES2022) כדי לשמר את השגיאה המקורית בעת השלכה מחדש.
היזהרו מ-Automatic Semicolon Insertion – לעולם אל תשברו שורה בין throw לביטוי.

