الفرق بين المراجعتين لصفحة: «JavaScript/try...catch»
لا ملخص تعديل |
ط استبدال النص - '\[\[تصنيف:(.*)\]\]' ب'{{SUBPAGENAME}}' |
||
سطر 182: | سطر 182: | ||
* معيار [http://www.ecma-international.org/ecma-262/5.1/#sec-12.14 ECMAScript 5.1]. | * معيار [http://www.ecma-international.org/ecma-262/5.1/#sec-12.14 ECMAScript 5.1]. | ||
* معيار [http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf ECMAScript 3rd Edition]. | * معيار [http://www.ecma-international.org/publications/files/ECMA-ST-ARCH/ECMA-262,%203rd%20edition,%20December%201999.pdf ECMAScript 3rd Edition]. | ||
[[تصنيف:JavaScript]] | [[تصنيف:JavaScript|{{SUBPAGENAME}}]] | ||
[[تصنيف:JavaScript Statement]] | [[تصنيف:JavaScript Statement|{{SUBPAGENAME}}]] |
المراجعة الحالية بتاريخ 15:36، 28 يناير 2018
التعبير البرمجي try...catch
يُستخدَم لتجربة قسم من التعابير البرمجية، ويُحدِّد طريقةً لمعالجة الاستثناءات إن رُمِيَت.
البنية العامة
try {
try_statements
}
[catch (exception_var_1) {
catch_statements_1
}]
...
[catch (exception_var_2) {
catch_statements_2
}]
[finally {
finally_statements
}]
try_statements
التعابير البرمجية التي ستُنفَّذ والتي قد ترمي استثناءً.
catch_statements_1
و catch_statements_2
التعابير البرمجية التي ستُنفَّذ إذا رُمي استثناءٌ في قسم try
.
exception_var_1
و exception_var_2
مُعرِّف يُستخدَم لتخزين قيمة كائن الاستثناء (exception object) المرتبط مع قسم catch
.
finally_statements
التعابير البرمجية التي ستُنفَّذ بعد إكمال تنفيذ try
، وهذه التعابير ستُنفَّذ سواءً رُمي استثناءٌ أم لم يرمَ.
الوصف
التعبير try
يتألف من قسم يحتوي على تعبير برمجي واحد أو أكثر (ويجب استخدام القوسين {}
حتى لو كان القسم يتألف من تعبيرٍ برمجيٍ واحد)، ويجب أن يضم قسم catch
أو قسم finally
واحد على الأقل؛ وهذا يعني أنَّ هنالك ثلاثة أشكال من تعابير try
:
try...catch
try...finally
try...catch...finally
يحتوي قسم catch
على التعابير البرمجي التي تُحدِّد ما الذي يجب فعله عند رمي استثناء في قسم try
؛ أي أنَّنا نريد أن ينجح تنفيذ التعابير البرمجي في قسم try
، وإن لم ينجح تنفيذها فنريد أن ننقل التحكم إلى قسم catch
؛ فلو رمى أيّ تعبير (أو دالة مستدعاة) في قسم try
استثناءً فسينتقل التحكم مباشرةً إلى قسم catch
، وإن لم يحدث أيّ استثناء في قسم try
فسيتم تخطي قسم catch
كليًّا.
قسم finally
سيُنفَّذ بعد تنفيذ قسم try
و catch
لكن قبل التعابير البرمجة التي تلي try
؛ وسيُنفَّذ دومًا سواءً رُميَ استثناءٌ أم لم يرمَ.
يمكنك تشعّب تعابير try
داخل بعضها بعضًا، وإذا لم يملك تعبير try
الداخلي قسم catch
مناسب، فسيُستعمَل قسم catch
لتعبير try
الأب.
لاحظ أنَّ بالإمكان استخدام try
لمعالجة الاستثناءات التي ترميها لغة JavaScript إضافةً إلى الاستثناءات الخاصة التي يرميها المستخدم.
أقسام catch
غير الشرطية
عند استخدام قسم catch
وحيد دون شرط معه، فسينتقل تنفيذ البرنامج إلى ذاك القسم في كل مرة يُرمى فيها استثناء؛ فمثلًا عند وقوع استثناء في الشيفرة الآتية فسينتقل التحكم مباشرةً إلى قسم catch
:
try {
throw 'myException'; // توليد استثناء
}
catch (e) {
// التعابير البرمجية اللازمة لمعالجة الاستثناء
logMyErrors(e); // تسجيل معلومات كائن الاستثناء
}
يُحدِّد قسم catch
مُعرِّفًا (اسمه e
في المثال السابق) الذي يحتوي على القيمة المرمية عبر تعبير throw
، لاحظ أنَّ JavaScript تُنشِئ مُعرِّفًا عند دخول قسم catch
وتتيحه للمجال المحلي (local scope) وسيبقى هذا المُعرِّف متاحًا حتى نهاية قسم catch
ولن يكون متوافرًا بعده.
أقسام catch
الشرطية
يمكن استخدام التعابير الشرطية if...else
داخل قسم catch
لاختبار تحقق شرط معيّن لكائن الاستثناءات؛ فسنختبر في المثال الآتي إذا كان الاستثناء المرمي من نوع TypeError
أو RangeError
أو EvalError
:
try {
myroutine(); // قد تؤدي هذه الدالة إلى رمي استثناء من أي نوع
} catch (e) {
if (e instanceof TypeError) {
// ...
} else if (e instanceof RangeError) {
// ...
} else if (e instanceof EvalError) {
// ...
} else {
// ...
logMyErrors(e);
}
}
مُعرِّف الاستثناء
عندما يرمى استثناءٌ في قسم try
فإنَّ exception_var
(مثلًا e
في catch (e)
) سيحتفظ بالقيمة المُحدَّدة عبر التعبير throw
، ويمكنك استخدام هذا المُعرِّف للحصول على معلومات حول الاستثناء الذي قد رُمِي.
لاحظ أنَّ هذا المُعرِّف محليٌ، أي أنَّه قد أنُشِئ عند دخول القسم catch
، ولن يكون متاحًا بعد انتهاء تنفيذ القسم catch
.
قسم finally
قسم finally
يحتوي على التعابير البرمجية التي ستُنفَّذ بعد قسم try
و catch
، لكن قبل التعابير التي تليها؛ لاحظ أنَّ قسم finally
سيُنفَّذ سواءً رُمي الاستثناء أم لم يرمَ، وإذا رمَي استثناءٌ فستُنفَّذ التعابير البرمجية في قسم finally
سواءً عالج قسم catch
الاستثناء أم لم يعالجه؛ ويمكنك استخدام قسم finally
لإنهاء تنفيذ السكربت بشكل جيد عند وقوع استثناء، مثل إغلاق الموارد التي استخدمها السكربت...
قد تجد من المستغرب وجود قسم يُنفِّذ التعابير البرمجية سواءً كان هنالك استثناءٌ أم لا؛ لكن هذا القسم له غرضٌ مفيدٌ ومهم؛ إذ إنَّ الشيفرات البرمجية التي تلي تعبير try
قد لا تُنفَّذ إن لم يُعالَج الاستثناء؛ وبالتالي لو وضعنا شيفرة إغلاق الموارد فيها فقد لا تُنفَّذ دومًا، أما لو وضعناها في قسم finally
فستُنفَّذ دومًا.
المثال الآتي سيفتح ملفًا على القرص الصلب ثم سنستخدم دالةً ضمن قسم try
للكتابة عليه (تذكَّر أنَّ JavaScript قد تُستخدَم في جهة الخادم، مما يعني إمكانية الوصول إلى الملفات المحلية)؛ وإذا حدث استثناءٌ وكان الملف مفتوحًا، فستُغلِق التعابير البرمجية الموجودة في قسم finally
الملف قبل انتهاء تنفيذ السكربت:
openMyFile();
try {
// حجز المورد
writeMyFile(theData);
}
finally {
closeMyFile(); // إغلاق المورد على كل حال
}
أمثلة
تعابير try
المتشعبة
هذا مثال عن تعبير try
له القسم finally
فقط، موجودٌ ضمن تعبير try
له القسم catch
فقط:
try {
try {
throw new Error('oops');
}
finally {
console.log('finally');
}
}
catch (ex) {
console.error('outer', ex.message);
}
// الناتج
// "finally"
// "outer" "oops"
أما لو أضفنا القسم catch
إلى تعبير try
الداخلي لمعالجة الاستثناء:
try {
try {
throw new Error('oops');
}
catch (ex) {
console.error('inner', ex.message);
}
finally {
console.log('finally');
}
}
catch (ex) {
console.error('outer', ex.message);
}
// الناتج
// "inner" "oops"
// "finally"
لاحظ أنَّ أيّ استثناء سيُعالَج مرةً واحدةً عبر أقرب قسم catch
إليه إلا إذا أُعيد رميه (بالتعبير throw
)، أي لو ظهرت أيّة استثناءات خارج تعبير try
الداخلي فستُعالَج عبر قسم catch
الخارجي.
إعادة القيم من قسم finally
إذا أُعيدت قيمة ضمن قسم finally
ستصبح القيمة النهائية المُعادة من قسم try...catch...finally
كله، بغض النظر عن أيّة تعابير return
موجودة في أقسام try
و catch
:
(function() {
try {
try {
throw new Error('oops');
}
catch (ex) {
console.error('inner', ex.message);
throw ex;
}
finally {
console.log('finally');
return;
}
}
catch (ex) {
console.error('outer', ex.message);
}
})();
// الناتج
// "inner" "oops"
// "finally"
دعم المتصفحات
الميزة | Chrome | Firefox | Internet Explorer | Opera | Safari |
---|---|---|---|---|---|
الدعم الأساسي | نعم | نعم | نعم | نعم | نعم |
مصادر ومواصفات
- مسودة المعيار ECMAScript Latest Draft.
- معيار ECMAScript 2015 (6th Edition).
- معيار ECMAScript 5.1.
- معيار ECMAScript 3rd Edition.