Block statement
جافاسكريبت تدعم مجموعة من البيانات المدمجة، وتحديدا التحكم في تدفق البيانات، التي يمكنك استخدامها لخلق قدرا كبيرا من التفاعل في التطبيق الخاص بك. يقدم هذا الفصل لمحة عامة عن هذه البيانات.
يحتوي هذا الفصل، مرجع الجافاسكريبت على تفاصيل شاملة عن التعليمات البرمجية. في جافاسكريبت، يتم استخدام رمز الفاصلة المنقوطة (;
) لانهاء التعليمات البرمجية.
ملحوظة: برامج الجافاسكريبت وبيانات الجافاسكريبت، غالباً ما تسمى تعليمات برمجية.
أي تعبير جافا سكريبت، هو أيضا تعليمة برمجية. راجع Expressions and operators للحصول على معلومات كاملة حول التعبيرات.
ابسط تعليمة برمجية هي التعليمة البرمجية بلوك block، التي تستخدم لاحتواء مجموعة من التعليمات البرمجية. البلوك محدد بواسطة الاقواس المتعرجة:
{ statement_1; statement_2; . . . statement_n; }
مثال
اغلب استخدامات البلوك، تكون مع تعليمات التحكم في التدفق ( مثل if
, for
, while
)
while (x < 10) {
x++;
}
لدينا هنا، { ;++x }
التعليمة البرمجة block.
هام: في جافا سكريبت قبل ECMAScript2015. البلوك لم يكن لديه نطاق. المتغيرات المستخدمة في البلوك، سيتم تغيير نطاقها الى النطاق العام وهو السكريبت، فتصبح متغيرات عامة متاحة لجميع التعليمات البرمجية في السكريبت، اما اذا وجد البلوك داخل دالة سيتم تغيير نطاقها لهذه الدالة، وبالتالي ستصبح متغيرات محلية متاحة لهذه الدالة فقط.
في جافا سكريبت، البلوكات "المستقلة" يمكن أن ينتج عنها نتائج مختلفة تماما عما كان سينتج في C أو جافا. فمثلا
var x = 1;
{
var x = 2;
}
console.log(x); // outputs 2
مخرجات التعليمة البرمجية اعلاه، ستكون 2 وذالك لان المتغير x المتواجد داخل البلوك والمتغير x المتواجد خارج البلوك لديهما نفس النطاق، او بمعنى اصح، كلاهما في النطاق العام وهو السكريببت. في C أو جافا. المخرجات ستكون 1.
ابتداءا من ECMAScript2015. استخدام المتغير let
داخل البلوك سينتج عنه سلوك مغاير. راجع let
صفحة المرجع للحصول على مزيد من المعلومات.
التعليمات الشرطية
التعليمة الشرطية هي مجموعة من الأوامر التي ستنفذ إذا تحقق شرطا معيناً. تدعم الجافاسكريبت اثنين من التعليمات الشرطية: هما if...else
و switch
.
التعليمة if...else
ستنفذ التعليمة البرمجية المرتبطة بالتعليمة if
اذا كان الشرط المنطقي يساوي true
. وكذالك ستنفذ التعليمة البرمجية المرتبطة بالتعليمة else
اذا كان الشرط المنطقي يساوي false
. استخدام التعليمة else
اختياري. فيما تكون التعليمة if
على الشكل التالي،
if (condition) { statement_1; } else { statement_2; }
الشرط condition
، يمكن ان يكون اي تعبير لإختبار ما اذا كان الشرط true
او false
راجع Boolean. لتوضيح ما الذي سيتم تنفيذه: في حالة ما اذا كان الشرط صحيح سيتم تنفيذ statement_1
، اما اذا كان الشرط غير صحيح سيتم تنفيذ statement_2
، يمكن ل statement_1
و statement_2
ان تكون اي تعليمات برمجية، بما فيها تعليمة if
اخرى.
يمكنك أيضا توسيع مجال التعليمات الشرطية باستخدام else if
لاختبار شروط متعددة في تسلسل، كما يلي:
if (condition_1) { statement_1; } else if (condition_2) { statement_2; } else if (condition_n) { statement_n; } else { statement_last; }
في حالة وجود شروط متعددة سيتم تنفيذ شرط واحد فقط، وهو الشرط المنطقي الذي سيتم اختباره ب true
. لتنفيذ عدة تعليمات برمجية، قم بتضمينها في التعليمة بلوك ({ ... }). من الجيد دائماً استخدام التعليمة بلوك، لا سيما عند استخدام التعليمات الشرطية المتداخلة :
if (condition) { statement_1_runs_if_condition_is_true; statement_2_runs_if_condition_is_true; } else { statement_3_runs_if_condition_is_false; statement_4_runs_if_condition_is_false; }
if (x = y) {
/* statements here */
}
إذا كنت بحاجة إلى استخدام تعيين بسيط في تعبير شرطي، استخدم أقواس إضافية حول التعيين. على سبيل المثال:
if ((x = y)) {
/* statements here */
}
القيم Falsy
القيم التالية تُقَيًم إلى false
عند اختباها في تعليمة شرطية (وتعرف ايضا بالقيم Falsy):
false
undefined
null
0
NaN
- السلسلة النصية الفارغة (
""
)
كل القيم الأخرى، بما في ذلك جميع الكائنات، تقيم إلى true
عندما يتم تمريرها إلى تعليمة شرطية.
لا تخلط بين القيم المنطقية الاولية true
و false
مع القيم true و false للكائن Boolean
. على سبيل المثال:
var b = new Boolean(false);
if (b) // this condition evaluates to true
if (b == true) // this condition evaluates to false
مثال
فى المثال التالى, الدالة checkData ستعود ب true
ادا كان عدد الحروف في الكائن Text يساوي ثلاثة، بخلاف ذالك، سيظهر التنبيه (alert
) وتعود ب false
.
function checkData() {
if (document.form1.threeChar.value.length == 3) {
return true;
} else {
alert('Enter exactly three characters. ' +
document.form1.threeChar.value + ' is not valid.');
return false;
}
}
التعليمة
switch
التعليمة switch
تسمح للبرنامج باختبار التعبير، وذالك من خلال مطابقة قيمة التعبير مع الحالة case
. إذا تم العثور على تطابق، البرنامج سينفذ التعليمة البرمجية المرتبطة بها. التعليمة switch
تكون على الشكل التالي:
switch (expression) { case label_1: statements_1 [break;] case label_2: statements_2 [break;] ... default: statements_def [break;] }
بداية يقوم البرنامج بالبحث عن الحالة case
التي تطابق قيمتها قيمة ال expression
، اذا وجدت، يقوم البرنامج بتنفيذ التعليمة البرمجية المرتبطة بها، اذا لم يجد ما يبحث عنه في اي من الحالات case
، سيقوم البرنامج بتنفيذ التعليمات البرمجية المرتبطة بالحالة default
اذا وجدت، لان وجود الحالة default
في التعليمة switch
اختياري. اذا لم يجد البرنامج اي حالة case
متطابقة ولا الحالة default
سيقوم بتنفيذ التعليمات البرمجية التي تلي التعليمة switch
.
التعليمة break
مرتبطة مع كل حالة case
، مهمتها جعل البرنامج يقفز خارج التعليمة switch
بمجرد تنفيذ التعليمة البرمجية، واستكمال تنفيذ التعليمات البرمجية التي تلي التعليمة switch
. بما ان وجود التعليمة break
اختياري، ففي حالة عدم وجودها سيقوم البرنامج بتنفيذ التعليمة التالية في switch
.
مثال
في المثال التالي، اذا كان fruittype
يساوي "Bananas"، سيقوم البرنامج بتنفيذ التعليمات البرمجية المرتبطة بالحالة 'case: 'Banana
. عندما سسيجد break
، سيقوم بايقاف switch
وينفذ التعليمات البرمجية التي تليها. اذا لم يجد break
سينفذ التعليمة البرمجية المرتبطة بالحالة 'case
: 'Cherries ايضا.
switch (fruittype) {
case 'Oranges':
console.log('Oranges are $0.59 a pound.');
break;
case 'Apples':
console.log('Apples are $0.32 a pound.');
break;
case 'Bananas':
console.log('Bananas are $0.48 a pound.');
break;
case 'Cherries':
console.log('Cherries are $3.00 a pound.');
break;
case 'Mangoes':
console.log('Mangoes are $0.56 a pound.');
break;
case 'Papayas':
console.log('Mangoes and papayas are $2.79 a pound.');
break;
default:
console.log('Sorry, we are out of ' + fruittype + '.');
}
console.log("Is there anything else you'd like?");
ملاحظة : لمزيد من التفاصيل حول التعليمة switch
.
التعليمات المعالجة للاستثناءات
من الثابت بقواعد الرياضيات انه لا يجوز القسمة على صفر بأي حال من الأحوال لذلك لن يتمكن البرنامج من تنفيذ العملية المطلوبة وستظهر للمستخدم رسالة خطا تنفيذي لا يمكنه تفاديها وعلى الأغلب أنها ستسبب بإغلاق البرنامج.
ولمعالجة أخطاء التنفيذ هذه وتحجيمها فبل حدوثها وفرت لنا لغات البرمجة وعلى رأسها الجافاسكريبت آلية تتمثل بوضع جمل استثنائية خاصة يتوقع من خلالها المبرمج أنواع أخطاء التنفيذ التي قد تحدث ويقوم ببرمجة حدث برمجي بكل استثناء ليتم تنفيذه بدلا من الخطا التنفيذي.بصفة عامة، الاستثناءات هي عبارة عن آلية برمجية لمعالجة أخطاء التنفيذ المحتمل وقوعها.
يمكنك قذف (توليد) الاستثناءات من خلال التعليمة throw
والتعامل معها باستخدام التعليمة try...catch
انواع الاستثناءات
في جافا سكريبت، يمكن استخدام الكائنات لقذف/توليد الاستثناءات. ومع ذلك، ليس كل الكائنات القاذفة هي نفسها. من الشائع إلى حد ما، قذف الاعداد أو السلاسل الحرفية كاخطاء، الا انه في كثير من الأحيان سيكون أكثر فعالية استخدام أحد أنواع الاستثناءات التالية، والتي أنشئت خصيصا لهذا الغرض:
التعليمة throw
التعليمة throw
تقذف الاخطاء. عند حدوث خطأ، عادة سوف تتوقف جافا سكريبت، وستولد رسالة للاعلان عن الخطأ. المصطلح التقني لهذه العملية هو : الجافاسكريبت ستقذف (throw) الخطأ. التعليمة throw
تمكتك من انشاء خطأ حسب رغبتك. المصطلح التقني لهذه العملية هو: اقذف استثناءا (throw an exception).
إستخدِم التعليمة throw
لقذف الإستثناء، عنما تريد قذف إستثناءا، عليك تحديد التعبير (expression
) الذي سيحتوي على القيمة التي ستقذف:
throw expression;
يمكنك قذف اي استثناء، وليس مجرد تعبيرات من نوع معين. التعليمة البرمجية التالية تقذف استثناءات لمختلف انواع البيانات:
throw 'Error2'; // String type
throw 42; // Number type
throw true; // Boolean type
throw {toString: function() { return "I'm an object!"; } };
// Create an object type UserException
function UserException(message) {
this.message = message;
this.name = 'UserException';
}
// Make the exception convert to a pretty string when used as a string
// (e.g. by the error console)
UserException.prototype.toString = function() {
return this.name + ': "' + this.message + '"';
}
// Create an instance of the object type and throw it
throw new UserException('Value too high');
لمزيد من المعلومات حول هذه التعليمة، راجع صفحة مرجع الجافا سكريبت throw
.
التعليمة
try...catch
التعليمة try...catch
تحدد بلوك من التعليمات البرمجية لتجربتها، و تنص على وجود واحد أو أكثر من الاستجابات التي ينبغي على الاستثناء ان يقذفها. إذا تم قذف الاستثناء، ستمسك به التعليمة try...catch.
التعليمة try...catch
تتكون من البلوك try
الذي سيحتوي على واحدة أو أكثر من التعليمات البرمجية، والبلوك catch
سيحتوي على التعليمات البرمجية التي تحدد ما يجب فعله اذا تم قذف الاستثناء من البلوك try
. بمعنى اخر، في معظم الحالات. نريد من التعليمات البرمجية داخل البلوك try
ان تسير بشكل طبيعي، وفي حالة حدوث مشاكل يمرّر التحكم الى البلوك catch
. إذا كانت هناك احدى التعليمات البرمجية داخل البلوك try
تقذف استثناءا، سيتم نقل التحكم فورا إلى البلوك catch
. وإذا لم يتم إرسال أي استثناء من داخل البلوك try
، فالبلوك catch
لن يقم باي شئ. هذه التعليمة البرمجية يمكن ان تحتوي على البلوك finally
والذي سينفذ بعد تنفيذ البلوك try
و catch
، وايضا سينفذ قبل تنفيذ التعليمات البرمجية التي تلي التعليمة try...catch
، اذا وجدت.
المثال التالى يستخدم التعليمة try...catch
. ويقوم باستدعاء دالة تعود باسم الشهر من مصفوفة بناء على القيمة التي تم تمريرها إلى الدالة. إذا كانت القيمة لا تتوافق مع رقم الشهر (1-12)، سيولّد استثناء مع القيمة "InvalidMonthNo" فيما تقوم التعليمة البرمجية في البلوك catch
بتعين القيمة unknown
إلى المتغير monthName
.
function getMonthName(mo) {
mo = mo - 1; // Adjust month number for array index (1 = Jan, 12 = Dec)
var months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul',
'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
if (months[mo]) {
return months[mo];
} else {
throw 'InvalidMonthNo'; //throw keyword is used here
}
}
try { // statements to try
monthName = getMonthName(myMonth); // function could throw exception
}
catch (e) {
monthName = 'unknown';
logMyErrors(e); // pass exception object to error handler -> your own function
}
The catch
block
يمكنك استخدام البلوك catch
للامساك بجميع الاستثناءات التي سيتم قذفها من البلوك try.
catch (catchID) { statements }
البلوك catch
يحدد الايدي catchID
الذي سيمسك القيمة المحددة من طرف التعليمة throw
، يمكنك استخدام هذا الايدي للحصول على معلومات حول الاستثناء الذي سيقذف. جافا سكريبت ستنشئ هذا الايدي عند دخوله الى البلوك catch
. يبدا عمر هذا الايدي من لحظة دخوله الى البلوك catch،
وينتهي عندما ينتهي البلوك catch
من التنفيذ.
على سبيل المثال، التعليمة البرمجية التالية ستقذف استثناءا. عند حدوث الاستثناء، سيتم نقل التحكم الى البلوك catch
.
try {
throw 'myException'; // generates an exception
}
catch (e) {
// statements to handle any exceptions
logMyErrors(e); // pass exception object to error handler
}
The finally
block
البلوك finally
سيحتوي على التعليمات البرمجية التي سيقوم بتنفيذها بعدما تنفذ البلوكات try
و catch
، وايضا سينفذ قبل تنفيذ التعليمات البرمجية التي تلي التعليمة try...catch
. سينفذ البلوك finally
سواء تم قذف الاستثناء ام لا، اذا تم قذف الاستثناء، ستنفذ التعليمات البرمجية في البلوك finally
حتى وان لم يتم معالجة الاستثناء في البلوك catch
.
يمكنك استخدام البلوك finally
لجعل السكريبت الخاص بك يفشل بأمان عند حدوث استثناء، على سبيل المثال، اذا كنت في حاجة إلى تحرير مورد، او لغلق ال flux، الخ. المثال التالي يفتح ملف ثم ينفذ التعليمات البرمجية لهذا ملف (server-side JavaScript يسمح لك بالوصول الى الملفات). اذا تم قذف استثناء في حين أن الملف مفتوح، البلوك finally
ستغلق هذا الملف قبل فشل السكريبت.
openMyFile();
try {
writeMyFile(theData); //This may throw a error
} catch(e) {
handleError(e); // If we got a error we handle it
} finally {
closeMyFile(); // always close the resource
}
عندما سيقوم البلوك finally
بارجاع قيمة، تصبح هذه القيمة قيمة الإرجاع من كامل المجموعة try-catch-finally
بغض النظر عن التعليمات البرمجية العائدة من البلوكات try
و catch
.
function f() {
try {
console.log(0);
throw 'bogus';
} catch(e) {
console.log(1);
return true; // this return statement is suspended
// until finally block has completed
console.log(2); // not reachable
} finally {
console.log(3);
return false; // overwrites the previous "return"
console.log(4); // not reachable
}
// "return false" is executed now
console.log(5); // not reachable
}
f(); // console 0, 1, 3; returns false
الكتابة فوق القيم العائدة من قبل البلوك finally
ينطبق أيضا على قذف الاستثناءات او اعادة القذف داخل البلوك catch
:
function f() {
try {
throw 'bogus';
} catch(e) {
console.log('caught inner "bogus"');
throw e; // this throw statement is suspended until
// finally block has completed
} finally {
return false; // overwrites the previous "throw"
}
// "return false" is executed now
}
try {
f();
} catch(e) {
// this is never reached because the throw inside
// the catch is overwritten
// by the return in finally
console.log('caught outer "bogus"');
}
// OUTPUT
// caught inner "bogus"
التعليمات try...catch المتداخلة
يمكن عمل واحدة او اكثر من التعليمات try...catch
المتداخلة. شرط عدم توفر try...catch
الداخلية على البلوك catch
، تتطلب وجود البلوك finally
والتعليمة try...catch
الخارجية سوف تستخدم البلوك catch
ليتم التحقق من المطابقة. راجع nested try-blocks في صفحة المرجع الخاص بالتعليمة try...catch
.
باستخدام الكائنات Error
اعتماداً على نوع الخطأ، من الممكن استخدام الخصائص name
و message
للحصول على رسالة أكثر دقة. عموما لدينا الخاصية name
التي ستعرض نوع الخطا الذي حدث (مثلا: DOMException
او Error
). والخاصية message
التي ستعرض رسالة الخطأ لوصف هذا الخطا (تستخدم عادة عندما نريد تحويل او عرض نص الخطأ). على سبيل المثال:
try {
throw new Error('Whoops!');
} catch (e) {
if( e.message === 'Whoops!'){
e.message = "Costume message";
}
console.log(e.name + ': ' + e.message); // Error: Costume message
}
اذا كنت ترغب في انشاء اخطاء خاصة بك، يمكتك استخدام المنشئ Error
من أجل الاستفادة من خصائصه. على سبيل المثال:
function doSomethingErrorProne() {
if (ourCodeMakesAMistake()) {
throw (new Error('The message'));
} else {
doSomethingToGetAJavascriptError();
}
}
....
try {
doSomethingErrorProne();
} catch (e) {
console.log(e.name); // logs 'Error'
console.log(e.message); // logs 'The message' or a JavaScript error message)
}
Promises
ابتداءا من ECMAScript2015. اصبح لجافاسكريبت الكائن Promise
والذي يسمح لك بالتحكم في التدفق والعمليات المتزامنة.
Promise هو احد هذه الحالات:
- pending (قيد الانتظار): الحالة الأولية، لم تَفِ أو تم رفضها.
- fulfilled (وفَّى): عملية ناجحة
- rejected (رُفِض): فشل العملية.
- settled (التسوية): إما وفى بوعد أو رفضه، ولكن ليس قيد الانتظار.
تحميل صورة ب XHR
مثال بسيط باستخدام Promise
و XMLHttpRequest
في مستودع الاكواد MDN GitHub. راجع المثال js-examples. يمكنك ايضا مراجعة see it in action. تم التعليق على كل خطوة لتمكينك من متابعة سير عملية Promise و XHR. هذا الإصدار من دون تعليقات، يعرض تدفق ال Promise:
function imgLoad(url) {
return new Promise(function(resolve, reject) {
var request = new XMLHttpRequest();
request.open('GET', url);
request.responseType = 'blob';
request.onload = function() {
if (request.status === 200) {
resolve(request.response);
} else {
reject(Error('Image didn\'t load successfully; error code:'
+ request.statusText));
}
};
request.onerror = function() {
reject(Error('There was a network error.'));
};
request.send();
});
}
للحصول على معلومات أكثر تفصيلاً، راجع Promise
في صفحة المرجع.