في JavaScript ، تعبيرات العبارات ، والبيانات هي الجملة أو الأمر بأكمله. مثلما ينتهي بيان اللغة الإنجليزية بفترة ما ، ينتهي JavaScript بفارق فاصلي.
يحسب التعبير قيمة ، لكن البيان يجعل شيئًا ما يحدث.
تتمثل إحدى طرق "تحقيق شيء ما" في حساب التعبيرات مع الآثار الجانبية. يمكن استخدام التعبيرات مع الآثار الجانبية مثل الواجبات ومكالمات الوظائف كبيانات منفصلة. هذا الاستخدام للتعبيرات كبيانات يسمى أيضًا عبارات التعبير. تتضمن البيانات المماثلة بيانات الإعلان ، والتي تستخدم لإعلان متغيرات جديدة أو تحديد وظائف جديدة.
برنامج JavaScript هو مجموعة من سلسلة من البيانات القابلة للتنفيذ. بشكل افتراضي ، يتم تنفيذ مترجم JavaScript بالتسلسل من أجل الكتابة. هناك طريقة أخرى "لتحقيق شيء ما" وهي تغيير ترتيب التنفيذ الافتراضي للبيان:
1. البيان الشرطي: يمكن لمترجم JavaScript تحديد ما إذا كان سيتم تنفيذ هذه العبارات أو تخطيها ، مثل بيانات التبديل.
2. بيان الحلقة: البيانات التي يمكن تنفيذها مرارًا وتكرارًا ، مثلما أثناء وجودها.
3. بيان القفز: يمكنك ترك المترجم المترجم يقفز إلى أجزاء أخرى من البرنامج لمواصلة التنفيذ ، مثل عبارات الفاصل والعودة والرمي
بعد ذلك ، ستقدم هذه المقالة بيانات مختلفة وبناء جملة في JavaScript. يلخص هذا الفصل هذه الجمل في النهاية. برنامج JavaScript ليس أكثر من مجرد مجموعة من العبارات مفصولة بالفصل ، لذلك بمجرد إتقان بيانات JavaScript ، يمكنك كتابة برنامج JavaScript.
1. بيان التعبير
بيانات المهمة هي عبارة تعبير مهمة نسبيًا. وظيفتهم هي تغيير قيمة المتغير ، تمامًا مثل تنفيذ عبارة تعيين: على سبيل المثال
نسخة الكود كما يلي:
تحية = "Hello" + name ؛
أنا *= 3 ؛
يرتبط مشغل الزيادة (++) والمشغل المتناقص (-) ببيان المهمة. وظيفتهم هي تغيير قيمة المتغير ، تمامًا مثل تنفيذ عبارة تعيين.
نسخة الكود كما يلي:
Counter ++ ؛
تتمثل الوظيفة المهمة لمشغل الحذف في حذف خصائص الكائن (أو عناصر صفيف) وكل ما يستخدم عمومًا كبيانات ، وليس كجزء من تعبير معقد.
نسخة الكود كما يلي:
حذف الثور.
مكالمات الوظائف هي فئة رئيسية أخرى من عبارات التعبير ، على سبيل المثال
نسخة الكود كما يلي:
تنبيه (تحية) ؛
window.close () ؛
على الرغم من أن وظائف العميل هذه هي تعبيرات ، إلا أنها لها تأثير معين على متصفح الويب. لذلك نعتقد أنه عبارة عن بيان أيضًا ، وليس من المنطقي استدعاء وظيفة بدون آثار جانبية ما لم تكن جزءًا من تعبير أو عبارة معقدة ، على سبيل المثال. من المستحيل تجاهل قيمة جيب التمام بشكل عشوائي ؛
Math.cos (x) ؛
بدلاً من ذلك ، للحصول على قيمة جيب التمام ، يجب عليك تعيينها إلى متغير بحيث يمكن استخدام هذه القيمة في المستقبل:
var cx = math.cos (x) ؛
مرة أخرى ، ينتهي كل سطر من الكود مع فاصلة فاصلة.
2. عبارات مركب وبيانات فارغة
يمكن تسلسل العديد من التعبيرات مع مشغل فاصلة لتشكيل تعبير. وبالمثل ، يمكن أن تخبرك JavaScript أيضًا أن عبارات متعددة متحدة معًا لتشكيل بيان مركب. فقط لف عبارات متعددة في أقواس مجعد. لذلك ، يمكن استخدام الأسطر التالية من التعليمات البرمجية كبيان منفصل في أي مكان في JavaScript ، فأنت تريد استخدام عبارة.
نسخة الكود كما يلي:
{
x = math.pi ؛
cx = math.cos (x) ؛
console.log ("cos (π) =" + cx) ؛
}
هناك عدة نقاط يجب ملاحظتها حول كتل العبارات: أولاً ، لا تتطلب كتل البيانات المنقصين. يجب أن تنتهي عبارات العناصر في الكتل باستخدام فاصلة فاصلة ، لكن الكتل لا.
ثانياً ، يتم وضع مسافة بادئة للخطوط الواردة في كتلة البيان ، وهو أمر غير ضروري ، لكن المسافة البادئة الأنيقة يمكن أن تجعل الكود أكثر قابلية للقراءة وأسهل الفهم.
ثالثًا ، ليس لدى JavaScript نطاق على مستوى الكتلة ، ولا تعتبر المتغيرات المعلنة في كتلة البيان مملوكة ملكية خاصة في كتلة البيان. (ارجع إلى القسم الأول من الفصل 3 ، 10)
تعتبر ممارسة الجمع بين العديد من العبارات في كتلة بيان كبيرة شائعة جدًا في برمجة JavaScript. تحتوي التعبيرات المماثلة عادةً على التعبيرات الفرعية ، تحتوي العديد من JavaScripts على بدائل أخرى. من حيث الشكل ، عادةً ما يسمح JavaScript بمجموعة بيانات لاحتواء استبدال. على سبيل المثال: يمكن أن يحتوي جسم الحلقة على بيان واحد فقط. باستخدام كتلة بيان ، يمكنك وضع أي عدد من العبارات في هذه الكتلة ، ويمكن استخدام كتلة البيان هذه كبيان.
في JavaScript ، عندما تريد استخدام عبارات متعددة كبيان واحد ، استخدم عبارة مطابقة بدلاً من ذلك. البيان الفارغ (البيان الفارغ) هو عكس ذلك تمامًا ، فهو يسمح لاحتواء بيانات 0. البيان الفارغ يبدو هكذا:
؛ // نيميكولون
من الواضح أن مترجم JavaScript لا يؤدي أي إجراءات عند تنفيذ عبارة فارغة ، لكن الممارسة أثبتت أن العبارات الفارغة تكون مفيدة أحيانًا عند إنشاء حلقة بجسم حلقة فارغ ، مثل ما يلي للحلقة
نسخة الكود كما يلي:
// تهيئة صفيف أ
لـ (i = 0 ؛ i <a.length ؛ a [i ++] = 0) ؛
في هذه الحلقة ، يتم الانتهاء من جميع العمليات في التعبير A [i ++] = 0 ، وليس هناك حاجة إلى جسم حلقة هنا. ومع ذلك ، يتطلب JavaScript أن يحتوي جسم الحلقة على بيان واحد على الأقل ، لذلك يتم استخدام فاصلة منفصلة فقط لتمثيل بيان فارغ.
لاحظ أن المنقصين في الجانب الأيمن من الحلقة for ، في حين أن الحلقة أو إذا كانت العبارة غير واضحة ، والتي قد تسبب بعض الأخطاء المميتة ، والتي يصعب تحديد موقعها. على سبيل المثال ، من المحتمل أن تكون نتيجة التنفيذ للرمز التالي تأثيرًا لا يريده المؤلف:
نسخة الكود كما يلي:
if ((a == 0) || (b == 0)) ؛ // هذا السطر من الكود لا يفعل شيئًا ...
o = فارغة ؛ // سيتم دائمًا تنفيذ سطر الرمز هذا
إذا كنت تستخدم عبارة فارغة لغرض خاص ، فمن الأفضل إضافة تعليقات في الكود ، والتي يمكن أن تشير بوضوح إلى أن هذا البيان الفارغ مفيد.
نسخة الكود كما يلي:
لـ (i = 0 ؛ i <a.length ؛ a [i ++] = 0) /*فارغة* /؛
3. بيان الإعلان
VAR والوظيفة هي بيانات إعلان تعلن أو تحدد المتغيرات أو الوظائف. تحدد هذه العبارات وتعيين المعرفات (أسماء متغيرة وأسماء الوظائف) لها ، والتي يمكن استخدامها في أي مكان في البرنامج. لا تفعل بيانات الإعلان شيئًا بنفسها ، ولكن لها معنى مهم: من خلال إنشاء متغيرات ووظائف ، يمكن تنظيم دلالات الكود بشكل أفضل.
ستتحدث الأقسام التالية عن عبارات VAR وبيانات الوظائف ، ولكن لا تحتوي على جميع محتويات المتغيرات والوظائف.
I.var
يتم استخدام عبارة VAR لإعلان متغير واحد أو أكثر. بناء الجملة الخاص به هو كما يلي:
var name_1 [= value_1] [، ... ، name_n [= value_n]]
يتبع الكلمة الرئيسية VAR قائمة بالمتغيرات المراد إعلانها. يمكن أن يكون لكل متغير في القائمة تعبير تهيئة يمكن استخدامه لتحديد قيمته الأولية. على سبيل المثال:
نسخة الكود كما يلي:
var i ؛ // متغير بسيط
var J = 0 ؛ // متغير مع القيمة الأولية
var p ، q ؛ // اثنين من المتغيرات
var Greet = "Hello" + name ؛ // تعبير تهيئة أكثر تعقيدًا
var x = 2.34 ، y = math.cos (0.75) ، r ، theta ؛ // العديد من المتغيرات
var x = 2 ، y = x * x ؛ // يستخدم المتغير الثاني المتغير الأول
var x = 2 ،
f = function (x) {return x * x} ، // كل متغير له صف واحد حصري
y = f (x)
إذا ظهرت عبارة VAR في جسم الوظيفة ، فإنها تحدد متغيرًا محليًا ، ونطاقه هو هذه الوظيفة. إذا كنت تستخدم عبارة VAR في الكود من المستوى الأعلى ، فإنها تعلن عن متغير عالمي ، وهو مرئي في جميع أنحاء JavaScript. في الفصل 3 ، القسم 10 ، يذكر أن المتغيرات العالمية هي خصائص للكائنات العالمية. بعد ذلك ، على عكس خصائص الكائنات العالمية الأخرى ، لا يمكن حذف المتغيرات المعلنة بواسطة VAR من خلال الحذف.
إذا لم يحدد المتغير في عبارة VAR تعبير تهيئة ، فإن قيمة هذا المتغير غير محددة في البداية. لذلك ، لا يتم تعريف قيمة المتغير قبل بيان الإعلان.
تجدر الإشارة إلى أنه يمكن أيضًا استخدام عبارة VAR كمكون من الحلقة أو لـ/في الحلقة. (مثل الإعلانات المتغيرة المعلنة قبل الحلقات ، ستكون المتغيرات المعلنة هنا "متقدمة") ، على سبيل المثال:
نسخة الكود كما يلي:
لـ (var i = 0 ؛ i <10 ؛ i ++) console.log (i) ؛
لـ (var i = 0 ، j = 10 ؛ i <10 ؛ i ++ ، j--) console.log (i * j) ؛
لـ (var i in o) console.log (i) ؛
لاحظ أنه لا يهم إذا كنت تعلن نفس المتغير عدة مرات.
ii.function
يتم استخدام وظيفة الكلمة الرئيسية لإعلان الوظائف. لقد تعلمنا تعبيرات الوظيفة (4.3). يمكن كتابة تعريفات الوظائف في شكل من أشكال البيان. على سبيل المثال: تتم كتابة تعريفان في رمز المثال التالي:
نسخة الكود كما يلي:
var f = function f (x) {return x + 1 ؛} // تعيين التعبير إلى متغير
الدالة f (x) {return x + 1 ؛} // الجملة التي تحتوي على أسماء متغيرة
بناء جملة إعلان الوظيفة هو كما يلي:
نسخة الكود كما يلي:
وظيفة funcname ([Arg1 [، arg2 [... ، argn]]]) {
البيانات
}
FuncName هو معرف الاسم للوظيفة المراد إعلانها. يتبع اسم الوظيفة قائمة المعلمات ، مفصولة بفواصل. عند استدعاء وظيفة ، تشير هذه المعرفات إلى المعلمات الفعلية التي تم تمريرها إلى الوظيفة.
يتكون جسم الوظيفة من عبارات javaScript ، مع عدم وجود حد لعدد العبارات ويتم إرفاقه بأقواس مجعد. عند تحديد وظيفة ، لا يتم تنفيذ العبارات في هيئة الوظيفة ، ولكنها مرتبطة بكائن الوظيفة الجديد المراد تنفيذه عند استدعاء الوظيفة. لاحظ أن الأقواس المجعد في بيانات الوظيفة ضرورية ، والتي تختلف عن كتل العبارات المستخدمة من قبل الحلقات وأقفال العبارات الأخرى. حتى إذا كان لدى جسم الوظيفة بيان واحد فقط ، فلا يزال هناك حاجة إلى أقواس مجعد لالتفاف.
نسخة الكود كما يلي:
وظيفة hyteus (x ، y) {
إرجاع Math.Sqrt (x * x + y * y) ؛
}
Hyteus (1 ، 2) //=>2.23606797749979
وظيفة الوجه (n) {// وظيفة عودية
إذا (n <= 1) العودة 1 ؛
إرجاع n * الوجه (n - 1) ؛
}
الوجه (11) // => 39916800
عادةً ما تظهر إعلانات الوظيفة في الجزء العلوي من رمز JavaScript ويمكن أيضًا أن تكون متداخلة داخل وظائف أخرى. ولكن عندما تتداخل ، لا يمكن أن تظهر إعلانات الوظيفة إلا في الجزء العلوي من الوظيفة المتداخلة. وهذا يعني: تعريف الوظيفة لا يمكن أن يظهر في إذا ، أو أو أو غيرها من البيانات.
مثل عبارة VAR ، لا يمكن حذف المتغيرات التي تم إنشاؤها بواسطة بيانات إعلان الوظيفة. ومع ذلك ، فإن هذه المتغيرات ليست قراءة فقط ، ويمكن إعادة كتابة القيم المتغيرة.
4. البيانات الشرطية
يتمثل البيان الشرطي في تنفيذ أو تخطي بعض البيانات من خلال تحديد ما إذا كان يجب تقييم قيمة التعبير المحدد. هذه العبارات هي "نقاط قرار" للرمز ، وتسمى أحيانًا "الفروع". إذا تم تنفيذ مترجم JavaScript بعد "مسار" الكود. البيان الشرطي هو نقطة الشوكة على هذا المسار. عندما يصل البرنامج إلى هذه النقطة ، يجب عليك تحديد مسار لمتابعة التنفيذ.
بيان IIF
إذا كان البيان عبارة عن بيان تحكم أساسي. لتكون دقيقة ، فإنه يسمح للبرنامج بتنفيذ مشروط. هناك شكلان من هذا البيان: الأول هو
نسخة الكود كما يلي:
إذا (التعبير)
إفادة
في هذا النموذج ، إذا كانت قيمة التعبير صحيحة ، قم بتنفيذ عبارة البيان ، وإذا كانت خاطئة ، فلا تنفذ البيان. على سبيل المثال،
نسخة الكود كما يلي:
إذا كان (اسم المستخدم == فارغًا) // إذا كان اسم المستخدم فارغًا أو غير محدد
اسم المستخدم = "جاك وونغ" ؛ // تحديده
تجدر الإشارة إلى أنه من الضروري إرفاق أقواس الحديقة للتعبير إذا كان البيان.
ينص جملة JavaScript على أنه إذا كان يجب أن تتبع الكلمات الرئيسية مع أقواس الحديقة ببيان. ومع ذلك ، يمكن دمج عبارات متعددة في واحدة باستخدام كتل بيان. لذلك ، يبدو شكل عبارة IF مثل هذا:
نسخة الكود كما يلي:
إذا (! العنوان) {
العنوان = "" ؛
Message = "الرجاء إرسال العنوان"
}
يقدم النموذج الثاني للبيان IF البند الآخر ، وينفذ المنطق الآخر عندما تكون قيمة التعبير خاطئة.
نسخة الكود كما يلي:
إذا (التعبير)
بيان 1
آخر
بيان 2
على سبيل المثال ، الرمز التالي
نسخة الكود كما يلي:
إذا (n == 1)
console.log ("1 رسالة جديدة") ؛
آخر
console.log ("لديك" + n + "رسالة جديدة") ؛
عند استخدام IF/else/else in that terted of If Dities ، يجب أن تكون حريصًا على التأكد من أن البيان ELONE يطابق البيان IF الصحيح. النظر في الرمز التالي:
نسخة الكود كما يلي:
i = j = 1 ؛
ك = 2 ؛
إذا (i == j)
إذا (j == k)
console.log ("i equals K") ؛
آخر
console.log ("i dosent equal j") ؛ //خطأ! !
في هذا المثال ، يشكل البيان الداخلي IF الجمل المطلوبة بواسطة البيان الخارجي IF. ومع ذلك ، فإن العلاقة المطابقة بين إذا لم تكن واضحة (فقط المسافة البادئة التي تعطي تلميحًا صغيرًا) وفي هذا المثال ، فإن التلميح الذي قدمه المسافة البادئة خاطئ ، لأن مترجم JavaScript يفهم ذلك.
نسخة الكود كما يلي:
إذا (i == j) {
إذا (j == k)
console.log ("i equals K") ؛
آخر
console.log ("i dosent equal j") ؛
}
مثل معظم لغات البرمجة ، فإن قواعد IF والآخر في JavaScript هي أن تتطابق مع البيان القريب دائمًا. من أجل جعل المثال قابل للقراءة ، وأسهل في الفهم ، وأكثر ملاءمة للصيانة والتصحيح ، يجب استخدام الأقواس المجعد.
نسخة الكود كما يلي:
إذا (i == j) {
if (j == k) {
console.log ("i equals K") ؛
} آخر {// crape الأقواس تجعل نتيجة الكود أكثر وضوحًا
console.log ("i dosent equal j") ؛
}
}
لدى العديد من المبرمجين عادةً إرفاق جسم IF وغيرها في أقواس مجعد (تمامًا كما في بيان مطابق مثل حلقة من الوقت). حتى لو كان هناك بيان واحد فقط لكل فرع ، فإن القيام بذلك يمكن أن يتجنب المشكلة الغامضة للبرنامج الآن.
II.ELSE إذا
يحدد بيان if/else أحد الفرعين عن طريق الحكم على نتيجة الحساب للتعبير. ماذا علي أن أفعل عندما يكون هناك العديد من الفروع في الكود؟ حل واحد هو استخدام البيان الآخر. وإلا إذا لم يكن بيان JavaScript حقيقي ، فهو مجرد وسيلة لكتابة عبارات متعددة إذا/آخر معًا.
نسخة الكود كما يلي:
if (n == 1) {
// تنفيذ كتلة الكود 1
} آخر إذا (n == 2) {
// تنفيذ الكود كتلة 2
} آخر إذا (n == 3) {
// تنفيذ كتلة الكود 3
} آخر {
// الشروط السابقة خاطئة ، ثم يتم تنفيذ كتلة الكود 4
}
لا يوجد شيء مميز حول هذا النوع من الكود. وهو يتكون من متعددة إذا كانت عبارات ، وكل عبارة إذا كانت عبارة أخرى تحتوي على بيان IF آخر. يمكن إكمال الرمز المكافئ بناء الجملة باستخدام النموذج المتداخل لـ IF IF ، ولكن مقارنةً بهذا ، من الواضح أن كتابة أخرى إذا كانت أوضح وفضل.
iii.switch
أثناء تنفيذ البرنامج ، يقوم عبارة if بإنشاء فرع ، ويمكنه استخدام آخر إذا كان يجب التعامل مع فروع متعددة. ثم ، عندما تعتمد جميع الفروع على قيمة نفس التعبير ، وإلا إذا لم يكن الحل الأفضل. في هذه الحالة ، من الممارسات المضيئة للغاية حساب التعبيرات مرارًا وتكرارًا في عبارات.
بيان التبديل مناسب للتعامل مع هذا الموقف. يتبع مفتاح الكلمات الرئيسية تعبيرًا محاطًا بأقواس الحديقة. ثم هناك كتل رمز محاطة بأقواس مجعد.
نسخة الكود كما يلي:
التبديل (التعبير) {
البيانات
}
ومع ذلك ، فإن بناء الجملة الكامل لبيان التبديل أكثر تعقيدًا من هذا. يتبع القضية تعبيرًا وقولون. تشبه الحالة إلى حد كبير لغة الترميز ، باستثناء أن لغة الترميز هذه لا تحتوي على اسم.
يرتبط فقط بالتعبيرات التي تتبعها. عند تنفيذ عبارة التبديل هذا ، يقوم أولاً بحساب قيمة التعبير ، ثم يجد ما إذا كان التعبير عن شرط الحالة هو نفس قيمة التعبير. (تتم مقارنة الشيء نفسه مع مشغل "==="). إذا تمت مطابقة القضية ، فسيتم تنفيذ الرمز المقابل. إذا تعذر العثور على حالة مطابقة ، فسيتم تنفيذ كتلة الكود في علامة "الافتراضي:". إذا لم يكن هناك "علامة افتراضية:" ، فسيقوم Switch بتخطي جميع كتل التعليمات البرمجية.
من السهل جدًا إرباك بيان التبديل ، وستكون المقدمة مع الأمثلة أكثر وضوحًا. بيان التبديل التالي يعادل بيان if/else الآن.
نسخة الكود كما يلي:
التبديل (n) {
الحالة 1: // إذا بدأ n === 1 من هنا
// تنفيذ كتلة الكود 1
استراحة؛
الحالة 2:
// تنفيذ الكود كتلة 2
استراحة؛
الحالة 3:
// تنفيذ كتلة الكود 3
استراحة؛
تقصير:
// تنفيذ كتلة الكود 4
استراحة؛
}
تجدر الإشارة إلى أنه يتم استخدام كسر الكلمات الرئيسية في نهاية كل عبارة حالة. سنقدم بيان الاستراحة لاحقًا. يمكن لبيان الاستراحة أن يجعل المترجم القفز من عبارة التبديل أو بيان الحلقة. في التبديل ، تشير الحالة فقط إلى نقطة انطلاق الرمز المراد تنفيذه ، ولكن لا تحدد نقطة النهاية. إذا لم يكن هناك بيان كسر ، فإن عبارة SWEST تبدأ في التنفيذ من الكود في علامة حالة المطابقة لقيمة التعبير ، وتنفيذ البيانات اللاحقة بدورها حتى نهاية كتلة رمز التبديل بالكامل. بالطبع ، إذا كنت تستخدم عبارة Switch في وظيفة ، فيمكنك استخدام Return لاستبدال Break. يتم استخدام كلاهما للعودة والكسر لإنهاء بيان التبديل ، والذي سيمنع أيضًا بيان حالة من الاستمرار في تنفيذ كتلة بيان الحالة التالية.
البيان التالي قريب من القتال الفعلي ، ويحول القيمة إلى سلسلة وفقًا لنوع القيمة.
نسخة الكود كما يلي:
وظيفة تحويل (x) {
التبديل (typeof x) {
حالة "رقم": // تحويل الأرقام إلى سداسي عشري
إرجاع X.ToString (16) ؛
حالة "سلسلة":
إرجاع "" + X + "" ؛ // إرجاع سلسلتين مع اقتباسات مزدوجة.
افتراضي: // استخدم طرقًا عادية لتحويل الأنواع الأخرى
سلسلة العودة (x) ؛
}
}
console.log (تحويل (100255114)) // => 5F9C58A
لاحظ أنه في المثالين أعلاه ، تتبع الكلمة الرئيسية للحالة رقم وسلسلة مباشرة ، وهو الاستخدام الأكثر شيوعًا للمحول في الممارسة ، لكن معيار ECMASCRIPT يسمح لكل كلمة رئيسية باتباع التعبيرات التعسفية.
يحسب عبارة Switch أولاً التعبير بعد الكلمة الرئيسية للتبديل ، ثم يحسب التعبير بعد كل حالة من أجل من أعلى إلى أسفل ، مع العلم أن قيمة التعبير المنفذة إلى العلبة وقيمة التعبير عن المفتاح متساوية. نظرًا لأن عملية المطابقة لكل حالة تكون في الواقع مقارنة "===" لمشغل الهوية ، وليس "==" ، فإن مطابقة التعبير والحالة لا تفعل أي تحويل نوع.
في كل مرة يتم تنفيذ بيان التبديل ، لا يمكن تنفيذ كل تعبيرات الحالات. لذلك ، يجب تجنب تعبيرات الحالة ذات الآثار الجانبية ، مثل تعبيرات مكالمات الوظائف وتعبيرات المهمة. الطريقة الأكثر أمانًا هي استخدام تعبيرات ثابتة في تعبيرات الحالات.
كما ذكرنا سابقًا ، إذا كان تعبير التبديل لا يتطابق مع جميع تعبيرات الحالة ، فسيتم تنفيذ كتلة البيان "الافتراضي:". إذا لم يكن هناك علامة "افتراضية:" ، سيتم تخطي عبارة Switch بالكامل. في المثال السابق ، تظهر العلامة "الافتراضي:" في نهاية المفتاح وهي وراء جميع علامات الحالات. بالطبع ، هذه هي الطريقة الأكثر شهرة والأكثر استخدامًا للكتابة. في الواقع ، يمكن وضع العلامة "الافتراضي:" في أي مكان ضمن عبارة التبديل.
5. حلقة.
لفهم البيانات الشرطية ، يمكنك التفكير في الكود في JavaScript كمسارات فرع. عبارات الحلقات هي بيانات حلقات تسمح بتنفيذ بعض التعليمات البرمجية بشكل متكرر. هناك أربعة عبارات حلقة في JavaScript: في حين ، تفعل/بينما ، ل ، ل/في. ستشرحها الأقسام التالية في وقت واحد. الحلقة الأكثر استخدامًا هي اجتياز عناصر الصفيف. (سوف يناقش 7.6 أساليب الحلقة الخاصة والحلقة الخاصة المحددة بواسطة فصول الصفيف بالتفصيل.)
آي
إذا كان البيان عبارة عن عبارة تحكم أساسية تستخدم لتحديد عبارات الفرع التي تنفذ البرنامج. مثل إذا ، فإن البيان الذي هو أيضًا عبارة عن بيان حلقة أساسية ، وبناء بناء الجملة كما يلي:
نسخة الكود كما يلي:
بينما (التعبير)
إفادة
قبل تنفيذ بيان الوقت ، يحسب مترجم JavaScript أولاً قيمة التعبير. إذا كانت قيمتها قيمة خاطئة ، فسيتخطى البرنامج البيان المنطقي في هيئة الحلقة وتنفيذ البيان التالي في البرنامج. إذا كانت قيمتها صحيحة ، فسيتم تنفيذ المنطق الموجود في بيان جسم الحلقة ، ثم يتم حساب قيمة التعبير التعبير. ستستمر الحلقة حتى تكون قيمة التعبير خاطئة. بمعنى آخر ، عندما يكون التعبير صحيحًا ، سيتم تنفيذ البيان في حلقة. لاحظ أن استخدام بينما (صحيح) سيؤدي إلى إنشاء حلقة ميتة.
بشكل عام ، لا نريد أن تقوم JavaScript بنفس العملية بشكل متكرر. في كل حلقة تقريبًا ، سيتغير أحد المتغيرات أو أكثر بشكل تكراري مع الحلقة. وذلك على وجه التحديد لأن هذه المتغيرات يتم تغييرها أن عمليات العبارات التي يتم تنفيذها في كل حلقة مختلفة. علاوة على ذلك ، إذا تم استخدام تغيير المتغير في التعبير ، فإن قيمة التعبير عن كل حلقة مختلفة أيضًا. هذا مهم جدا. التعبير المسؤول عن القيمة الأولية للقيمة الحقيقية هو دائمًا القيمة الحقيقية ، ولن تنتهي الحلقة. يوضح المثال أدناه أنه بينما تقوم الحلقة بإخراج القيم 0-9.
نسخة الكود كما يلي:
var count = 0 ؛
بينما (العد <10) {
console.log (count) ؛
count ++ ؛
}
يمكن العثور على أنه في هذا المثال ، تكون القيمة الأولية لعدد المتغير هي 0 ، وخلال الحلقة ، يتم زيادة قيمتها بمقدار واحد في كل مرة ، عندما يتم تنفيذ الحلقة عشر مرات. يتم برمجة قيمة التعبير خاطئة ، وبعد ذلك ستنتهي ، وسيقوم مترجم JavaScript بتنفيذ البيان التالي للبرنامج. معظم الحلقات لديها متغير مضاد مثل العد. على الرغم من أن العدادات غالبًا ما تستخدم أسماء متغيرة مثل IJK ، إذا كنت ترغب في جعل الكود أكثر قابلية للقراءة ، فيجب عليك استخدام أسماء بناء الجملة أكثر تحديدًا.
ii.do/while
تشبه الحلقة DO/بينما تشبه إلى حد كبير الحلقة ، إلا أنها تكتشف تعبير الحلقة عند ذيل الحلقة بدلاً من الأعلى ، مما يعني أن جسم الحلقة يتم تنفيذه مرة واحدة على الأقل. بناء جملة DO/بينما الحلقة هي كما يلي:
نسخة الكود كما يلي:
يفعل
إفادة
بينما (التعبير) ؛
لا/في حين أن الحلقات ليست شائعة الاستخدام كما هو الحال في الحلقات. هذا لأنه ليس من الشائع في الممارسة العملية الرغبة في تنفيذ الحلقات مرة واحدة على الأقل. فيما يلي مثال على do/بينما حلقة
نسخة الكود كما يلي:
وظيفة printarray (a) {
var len = A.Length ،
أنا = 0 ؛
إذا (len == 0)
console.log ("صفيف فارغ") ؛
آخر
يفعل {
console.log (a [i]) ؛
} بينما (++ i <len) ؛
}
printarray ([1،5،2،6])
هناك نوعان من الاختلافات في بناء الجملة بين Do/بينما الحلقات والطبيعية أثناء الحلقات. أولاً ، تتطلب حلقة DO أن يتم استخدام الكلمة الرئيسية لتحديد بداية الحلقة ، واستخدم بينما متغير لتحديد نهاية الحلقة وإدخال حالة الحلقة للحكم ؛ ثانياً ، على عكس الحلقة ، تستخدم حلقة DO نهاية منقوطة. إذا تم إرفاق جسم الحلقة في أقواس مجعد ، فإن الحلقة بينما لا تنتهي مع فاصلة فاصلة.
ثالثا
يوفر البيان FOR هيكل التحكم في بيان حلقة أكثر ملاءمة من الوقت. يبسط البيان وضع الحلقة الشائعة الاستخدام. معظم الحلقات لها متغيرات مضادة محددة. تتم تهيئة هذا المتغير قبل بدء الحلقة ، ثم تحقق من قيمته قبل كل حلقة. أخيرًا ، يكون المتغير المضاد ذاتيًا ، وإلا سيتم تعديله بعد انتهاء الدورة وقبل الحكم التالي. في هذا النوع من الحلقة ، تكون العمليات الرئيسية الثلاثة للعداد هي التهيئة والاكتشاف والتحديث. تعلن البيان من أجل هذه العمليات الثلاثة صراحةً كجزء من بناء جملة الحلقة ، كل منها يستخدم تعبيرًا لتمثيله. بناء جملة البيان لـ for هو كما يلي:
نسخة الكود كما يلي:
لـ (تهيئة ؛ اختبار ؛ الزيادة)
إفادة
يتم فصل التعبيرات الثلاثة للتهيئة والاختبار والزيادة بواسطة فاصلة فاصلة. إنهم مسؤولون عن تهيئة العمليات ، وحكم الحالة الدورية وتحديث متغيرات العداد. إن وضعهم على السطر الأول من الحلقة يجعل من السهل فهم ما تفعله الحلقة ، ويمنع أيضًا نسيان تهيئة المتغير المضاد أو زيادة.
أسهل طريقة لشرح كيفية عمل حلقة A هي سرد ما يعادلها أثناء حلقة
نسخة الكود كما يلي:
تهيئة
بينما (اختبار) {
إفادة
زيادة؛
}
بمعنى آخر ، يتم تنفيذ تعبير التهيئة مرة واحدة فقط قبل بدء الحلقة. يجب أن يكون للتعبير عن التهيئة آثار جانبية (عادة ما يكون بيان المهمة). يتيح JavaScript أيضًا تعبيرات التهيئة مع بيانات إعلان Var Variable ، بحيث يمكن إعلان وتهيئة متغير. قبل كل حلقة ، سيتم تنفيذ تعبير الاختبار ، وسيتم الحكم على نتيجة التعبير لتحديد ما إذا كان سيتم تنفيذ جسم الحلقة. قبل كل حلقة ، سيتم تنفيذ تعبير الاختبار وسيتم تحديد النتيجة ما إذا كان سيتم تنفيذ هيئة الحلقة. إذا كانت نتيجة الاختبار هي القيمة الحقيقية ، فسيتم تنفيذ العبارة الواردة في هيئة الحلقة. وأخيرا ، تنفيذ التعبير زيادة. أيضا من أجل الفائدة ، يجب أن يكون للتعبير عن الزيادة هنا آثار جانبية. بشكل عام ، إنه إما تعبير مهمة أو تعبير يتكون من "++" و "-" المشغلين.
ما سبق بينما يمكن كتابة الحلقة باستخدام حلقة من أجل
نسخة الكود كما يلي:
لـ (var count = 0 ؛ count <10 ؛ count ++)
console.log (العد)
بالطبع ، بعض الحلقات أكثر تعقيدًا ، ويتم تكرار متغيرات متعددة في وقت واحد في الحلقة. في JavaScript ، يجب استخدام هذه الحالة مع مشغل فاصلة ، والذي يجمع بين تعبير التهيئة وتعبير التلقائي في تعبير واحد للاستخدام في حلقة.
نسخة الكود كما يلي:
var i ، j ؛
لـ (i = 0 ، j = 10 ؛ i <10 ؛ i ++ ، j--)
console.log (i * j) ؛
حتى الآن ، فإن متغيرات الحلقة في رمز العينة كلها أرقام. بالطبع ، الأرقام هي الأكثر استخدامًا ، ولكنها ليست ضرورية. يستخدم الرمز التالي A for loop لتجاوز نتائج بيانات الجدول وإرجاع الكائن الأخير في القائمة المرتبطة (أي الكائن الأول الذي لا يحتوي على السمة التالية)
نسخة الكود كما يلي:
وظيفة ذيل (س) {// إرجاع كائن العقدة الأخير من القائمة المرتبطة
لـ (؛ O.Next ؛ o = o.next) /*فارغة* / / / /تنفيذ اجتياز بناءً على ما إذا كانت O.Next هي القيمة الحقيقية
العودة س ؛
}
تجدر الإشارة إلى أن هذا الرمز لا يحتوي على تعبيرات تهيئة ، ويمكن تجاهل الأشخاص وأحد التعبيرات الثلاثة في الحلقة من أجل ، ولكن لا غنى عن الفصلين. إذا تم حذف تعبير الاختبار ، فستكون حلقة ميتة. أيضا مع نوع (ture) ، إحدى الطرق لكتابة حلقة ميتة هي ل (؛ ؛).
iiii.for/in
يستخدم For/in العبارة الكلمة الرئيسية ، ولكنه نوع مختلف من الحلقة العادية للحلقة. بناء الجملة لـ For/in Loop كما يلي
نسخة الكود كما يلي:
لـ (متغير في الكائن)
إفادة
عادةً ما يكون المتغير اسمًا متغيرًا ، أو تعبيرًا يمكن أن ينتج عن القياس أو المتغير الذي تم إعلانه من خلال عبارة VAR. على أي حال ، إنها قيمة تنطبق على الجانب الأيسر من تعبير المهمة. الكائن هو تعبير ، ونتيجة هذا التعبير هو كائن. وبالمثل ، فإن البيان عبارة عن بيان أو كتلة من العبارات التي تشكل جسم الحلقة.
استخدام حلقة للتكرار من خلال عناصر الصفيف أمر بسيط للغاية
نسخة الكود كما يلي:
var a = [1 ، 3 ، 5 ، "44"] ؛
لـ (var i = 0 ؛ i <A.Length ؛ i ++) // i يمثل فهرس عناصر الصفيف
console.log (a [i]) // عناصر الإخراج من كل صفيف
يتم استخدام For/in Loop لتجاوز خصائص أعضاء الكائنات المريحة
نسخة الكود كما يلي:
لـ (var p في O) // تعيين اسم السمة إلى المتغير p
console.log (o [p]) ؛ // إخراج قيمة كل سمة
في عملية تنفيذ POT/in البيان ، يحسب مترجم JavaScript أولاً تعبير الكائن. إذا كان التعبير فارغًا أو غير محدد ، فسيقوم مترجم JavaScript بتخطي الحلقة وتنفيذ الكود اللاحق. إذا كان التعبير يساوي قيمة بدائية ، فسيتم تحويل هذه القيمة البدائية إلى كائن Wrapper (القسم 3.6). خلاف ذلك ، فإن التعبير نفسه هو بالفعل كائن. يعدد JavaScript خصائص الكائن بدوره لتنفيذ الحلقة. ومع ذلك ، قبل كل حلقة ، تحسب JavaScript قيمة التعبير المتغير ويعين اسم السمة (سلسلة) لها.
تجدر الإشارة إلى أنه طالما أن/في الحلقة ، يمكن اعتبار قيمة varibale بمثابة LVALUE لتعبير المهمة ، ويمكن أن يكون أي تعبير. يتم حساب هذا التعبير كل حلقة ، مما يعني أن القيمة التي يحسبها قد تكون مختلفة في كل مرة يتم فيها حلقاتها. على سبيل المثال ، يمكنك استخدام الكود التالي لنسخ جميع خصائص الكائن في صفيف:
نسخة الكود كما يلي:
var o = {x: 1 ، y: 2 ، z: 3} ؛
var a = [] ، i = 0 ؛
لـ (a [i ++] في o) /*فارغة* /؛
document.write (a) // => x ، y ، z
صفائف JavaScript هي مجرد كائن خاص ، لذلك يمكن لـ/في الحلقة تعداد فهارس البيانات مثل خصائص الكائنات. على سبيل المثال ، يمكن لإضافة هذا الرمز بعد الرمز أعلاه تعداد فهرس البيانات 0 ، 1 ، 2:
نسخة الكود كما يلي:
var o = {x: 1 ، y: 2 ، z: 3} ؛
var a = [] ، i = 0 ؛
لـ (a [i ++] في o) /*فارغة* /؛
document.write (a) // => x ، y ، z نسخ خصائص كائن
ل (أنا في أ)
document.write (i) // => end data index 0 1 2
في الواقع ، لا يجتاز For/in Loop جميع خصائص الكائن. سيتم اجتياز سمات "التعداد" فقط (انظر 6.7). نظرًا لأن الأساليب المدمجة التي يحددها Core JavaScript Language ليست "قابلة للتعداد". على سبيل المثال ، تحتوي جميع الكائنات على toString () ، ولكن for/in loop لا تعدد الخاصية tostring (). بالإضافة إلى الطرق المدمجة ، هناك العديد من الكائنات المدمجة التي لا يمكن تعدادها. جميع السمات والأساليب المحددة في الكود لا يمكن تعدادها (سيتم ذكر القسم 6.7 ، ولكن هناك وسيلة خاصة في ECMASCRIPT5 التي يمكن أن تجعل السمات غير قابلة للتعداد).
يمكن للكائنات أن ترث خصائص الكائنات الأخرى ، ويمكن أيضًا تعداد الخطوط المخصصة للخصائص المخصصة (6.2.II) باستخدام/in.
إذا كان الجسم for/in loop يحذف خاصية غير مؤهلة ، فلن يتم تعداد هذه الخاصية مرة أخرى. إذا قام جسم الحلقة بتعريف خصائص جديدة للكائن ، فلا يتم تعداد هذه الخصائص عادة (ولكن بعض تطبيقات JavaScript يمكن أن تعدد الخصائص المضافة في الجسم الحلقة).
ترتيب تعداد السمة
لا تحدد مواصفات ECMASCRIPT بترتيب/في حلقة تعداد خصائص الكائن. ولكن في الواقع ، تعدد جافا سكريبت الشركة المصنعة للمتصفح السائد خصائص الكائنات البسيطة بترتيب تعريفات السمات ، والخصائص المحددة أولاً يتم تعدادها أولاً. إذا تم إنشاء كائن في شكل كمية مباشرة ، فسيتم تعداده بالترتيب الذي تظهر فيه الخصائص في الكمية المباشرة. (تعتمد بعض مكتبات الشبكة وجافا سكريبت على أمر التعداد هذا ، في حين أن مصنعي المتصفح في الغالب لا يعدلون هذا الطلب). في الحالات التالية ، يعتمد أمر التعداد على التنفيذ المحدد (وليس التفاعل)
1. الكائنات ترث سمات قابلة
2. الكائن له خصائص من فهرس مجموعة عدد صحيح
3. استخدم حذف لحذف الخصائص الموجودة للكائن
4. استخدم Object.DefineProperty () أو طرق مماثلة لتغيير خصائص الكائن
6. القفز
في JavaScript ، نوع من البيان هو بيان القفز. من فهم بيان ، يمكن أن يجعل تنفيذ JavaScript يقفز من وضع واحد إلى موقف واحد.
بيان الاستراحة هو القفز إلى نهاية حلقة أو بيان آخر. ينهي بيان متابعة تنفيذ هذه الحلقة ويبدأ تنفيذ الحلقة التالية. يمكن تسمية البيانات الموجودة في JavaScript أو تصنيفها ، يمكن أن تحدد الحلقات المستهدفة أو علامات العبارات الأخرى.
يسمح بيان الإرجاع للمترجم بالخروج من تنفيذ جسم الوظيفة. وتوفير قيمة إرجاع هذه المكالمة. يطلق بيان الرمي أو يلقي استثناءً ، والذي يتم استخدامه مع عبارة المحاولة/catch/أخيرًا ، والذي يحدد منطق رمز معالجة الاستثناء. هذا بيان قفزة معقد. عند إلقاء استثناء ، سيقفز البرنامج إلى أقرب نجم استثناء مغلق. يمكن أن يكون برنامج الاستثناء هذا في نفس الوظيفة أو في مكدس الاتصال على مستوى أعلى.
بعد ذلك ، صف كل بيان قفزة
أنا. بيان العلامة
يمكن تصنيف بيان ، وتتكون الملصق من المعرف والقولون قبل البيان:
المعرف: بيان
من خلال تحديد علامة لبيان ، يمكنك الرجوع إلى هذا البيان باسم العلامة في أي مكان في البرنامج. يمكنك تحديد الملصقات لبيانات متعددة ، على الرغم من أنها أكثر فائدة فقط عند تحديد الملصقات لكتل العبارات ، مثل عبارات الحلقة أو بيانات الحكم المشروطة. من خلال تحديد اسم علامة للحلقة ، يمكنك استخدام الفاصل والمتابعة داخل جسم الحلقة للخروج من الحلقة أو التحدي المباشر لبدء الحلقة التالية. break and continue are the only statements in JavaScript that can use statement tags (this chapter will be discussed next). The following example, where the while loop defines a tag, and the continue statement uses this tag:
نسخة الكود كما يلي:
mainloop: while (token != null) {
//忽略这里代码...
continue mainloop; //跳转到下一次循环
//忽略这里的代码...
}
这里做标签的indentifier必须是一个合法的javascript标识符,而不能是一个保留字。标签的命名空间和变量或函数的命名空间是不同的,因此可以使用同一个标识符作为语句标签和作为变量名或函数名。语句标签只在它所起作用的语句(当然可以在它的子句)内是有定义的。一个语句标签不能和它内部的语句标签重名,但在两个代码不相互嵌套的情况下是可以出现同名语句标签的。带有标签的语句还可以带有标签,也就是说,任何语句可以有很多个标签。
ii.break
单独使用break语句的作用是立即退出最内存的循环或switch语句。它的语法如下:
استراحة؛
由于它能够使循环和switch语句退出,因此这种形式的break只能出现在这类语句中才是合法的。
我们在switch语句的例子中已经见到果break语句。在循环中,无论出于什么原因,只要不想继续执行整个循环,就可以用break提前退出。当循环终止条件非常复杂时,要函数体内使用break语句实现这样些条件判断的做法要比直接在循环表达式中写出这个复杂的终止条件做法简单的多。
下面的例子中循环遍历整个数组元素来查找某个特定的值,当整个数组遍历完成后正常退出循环,如果找到了需要查找的数组元素,则使用break语句退出循环:
نسخة الكود كما يلي:
for (var i = 0; i < a.length; i++) {
if (a[i] == target) break;
}
javascript中同样允许break关键字后跟随一个语句标签,(只有标识符,没有冒号)
break labelname;
当break和标签一块使用时,程序将跳转到这个标签所识别的语句块的结束,或者直接终止这个闭合语句块的执行。当没有任何闭合语句块指定break所用的标签,这时会产生一个语法错误。当使用这种形式的break语句时,带标签的语句不应该是循环或者switch语句,因为break语句可以“跳出”任何闭合的语句块。这里的语句可以是由花括号组起来的一组语句,使用同一个标签来识别一组语句。
break关键字和labelname之间不能换行。因为javascript可以给语句自动补全省略掉的分号,如果break关键字和标签之间有换行,javascript解释器会认为你在使用break不带标签的最简形式,因此会在break后补充分号.
当你希望通过break来跳出非就近的循环体或者switch语句时,就会用到带标签的break语句。下面是示例代码:
نسخة الكود كما يلي:
var matrix = getData(); //从某处获得一个二维数组
//将矩阵中所有元素进行求和
var sum = 0,
success = false;
//从签名处开始,以便在报错时推出程序。
compure_sum: if (matrix) {
for (var x = 0; x < matrix.length; x++) {
var row = matrix[x];
if (!row) break compure_sum;
for (var y = 0; y < row.length; y++) {
var cell = row[y];
if (isNaN(cell)) break compure_sum;
sum += cell;
}
}
success = true;
}
//break语句跳转至此
//如果success =false条件到达这里,说明我们给出的矩阵中有错误
//否则对矩阵中所有的元素进行求和
最后,需要注意的是,不管break语句带不带标签,它的控制权都无法越过函数的边界。比如:对于一条带标签的函数定义语句来说,不能通过函数内部通过这个标签来跳转到函数外部.
iii.continue语句
continue语句和break语句非常类似,但它不退出循环,而是转而执行下一次循环。continue语句的语法和break的语句语法一样简单
يكمل؛
continue语句会也会带有标签
continue lebname;
不管continue语句带不带标签,它只能在循环体使用,在其它地方使用将会报语法错误。
当执行到continue语句的时候,当前的循环逻辑就终止了,随即执行下一次循环,在不同类型的循环中,continue的行为也有区别
1.在while循环中,在循环开始处指定expression会重复检测,如果检测结果为true,循环体会从头执行。
2.在do/while循环中,程序的执行至今跳转到循环的结尾处,这时会重新判断循环条件,之后才会继续下一次循环。
3.在for循环中,首先会计算自增表达式,然后再检测test表达式,用以判断是否执行循环体。
4.在for/in循环中,循环开始遍历下一个属性名,这个属性名赋给了指定的变量。
需要注意continue语句在while和for循环中的区别,while循环直接进入下一轮的循环条件判断,但for循环首先计算器increment表达式,然后判断循环条件。之前的章节讨论了和while循环“等价”的for循环行为。但由于continue在这两种循环中行为表现不同,因此使用while循环不可能完美的模拟等价的for循环。
下面这段代码展示了不带标签的continue语句,产生一个错误的时候跳过当前循环的后续逻辑
نسخة الكود كما يلي:
for (i = 0; i < data.length; i++) {
if (!data[i]) continue; //不能处理undefined数据
total += data[i];
}
和break语句类似,带标签的continue语句可以用在嵌套的循环中,用以跳出层次嵌套的循环体逻辑。同样和break语句类似,在continue语句和labname之间不能有换行。
iiii.return
回想一下,函数调用的一种表达式,而且所有的表达式都有值。函数中的return语句即是指函数调用后的返回值。这里是return语句的语法:
return expression;
The return statement can only appear in the function body. If not, it will report a syntax error. When the return statement is executed, the function terminates the execution and returns the value of the expression to the calling program. على سبيل المثال:
نسخة الكود كما يلي:
function square(x) {return x * x} //一个包含return的语句函数
square(4) //执行为16
如果没有return语句,则函数调用仅依次执行函数体内的每一条语句直到函数结束,最后返回调用程序。这种情况下,调用表达式的结果是undefined。return语句经常作为函数内最后的一条语句出现,但并不是说一定一定要放在函数的最后,即使在执行return语句的时候还有很多代码没有执行到,这时候函数也还返回调用程序。
The return statement can be used alone without having expression, so the function will also want to call the program to return undefined. على سبيل المثال:
نسخة الكود كما يلي:
//如果参数是null或者undefined则立即返回
if (!o) return;
//其它逻辑
由于javascript可以自动插入分号,因此,return关键字和它后面的表达式之间不能有换行。
iiiii.throw语句
所谓异常(excepion)是当发生了某种异常情况或错误时产生的一个信号。抛出异常,就是用信号通知发生了错误或异常状况。捕获异常是指处理这个信号,抛出异常,就是用信号通知发生了错误或异常状况。捕获异常是指处理这个信号,即采取必要的手段从异常中汇丰。在javascript中,当产生运行时错误或者程序使用throw语句时就会显式的抛出异常。使用try/catch/finally语句可以捕获异常,下一节会对它作详细介绍。
throw语句的语法如下:
throw expression
expression的值可以是任意类型的。可以抛出一个代表错误码的数组,或者包含可错误消息的字符串。当javascript解释器抛出异常的时候,通常采用Eeeor类型或其子类型,当然也可以使用它们。一个error对象有一个那么熟悉表示错误类型,一个message属性用来传递构造函数的字符串(参照第三部分的Error类),在下面的例子中,当使用非法参数调用函数时就抛出一个Error对象:
نسخة الكود كما يلي:
function fa(x) {
//如果输入的参数是非法的,则抛出一个异常
if (x < 0) throw new Error("x不能是负数。");
//否则计算出一个值,正常地返回它
for (var f = 1; x > 1; f *= x, x--) /*empty*/;
return f;
}
当抛出异常时,javascript解释器会立即停止当前正在执行的逻辑,并跳转至就近的异常处理程序。异常处理程序用try/catch/finally语句的catch从句编写的。如果抛出的异常没有一条关联catch从句,解释器会检测更高层的闭合代码块,看它是否关联相关的异常处理程序。以此类推,直到扎到一个异常处理的程序为止。
如果抛出的异常函数没有处理它的try/catch/finally语句,异常将向上传播到调用该函数的代码。这样的话,异常就会沿着javascript方法的词法结构和调用栈向上传播。如果没有找到任何异常处理的程序,javascript将吧异常当成程序错误来处理,并报告给用户。
iiiiii.try/catch/finally语句
try/catch/finally语句是javascript的异常处理机制。其中try从句定义了需要处理的异常所在代码块。catch语句跟随在try从句之后,当try块从某处发送了异常时,调用了catch内的代码逻辑。catch从句跟随finnlly块,后者防置了清理代码,不管try块中是否产生了异常,finnally块内的逻辑总会执行。尽管catch和finally都是可选的,但try从句只杀二者之一与组成完整的语句。try、catch和finally语句块都需要花括号括起来,这里的花括号是必须的。即使从句中只有一条语句也不能省略花括号。
下面的代码说明了try/catch/finlly的语法和使用目的:
نسخة الكود كما يلي:
يحاول{
//通常来讲,这里的代码会从头执行到尾而不会产生任何问题,
//但有时会抛出一个异常,要么是由throw语句直接抛出异常
//要么通过调用一个方法间接抛出异常
}
catch(e){
//当且仅当try抛出了异常,才会执行这里的代码
//这里可以通过局部变量e来获得对Error对象或者抛出的其它值的引用
//这里的代码可以基于某种原因处理这个异常,也可以忽略这个异常。
//还可以通过throw语句重新抛出异常
}
أخيراً{
//不管try语句块是否抛出看异常,这里的逻辑总会执行,终止try的语句块方式有:
//1)正常终止,执行完语句块的最后一条语句
//2)通过break,continue或return语句终止
//3)抛出一个异常,异常被catch从句捕获
//4)抛出一个异常,异常未被捕获,继续向上传播
}
我们注意到,关键字catch后跟随了一对圆括号,圆括号内是一个标识符。这个标识符和函数参很像。当捕获一个异常时,把这个异常相关的值(比如Error对象)赋值给这个参数。和普通的变量不同,这条catch子句中的标识符具有块级作用域,它只在catch语句块内有定义。
这里有一个关于try/catch语句更实际的例子,这里使用了前面章节中提到factorial()方法,并使用客户端javascript方法prompt()和alert()来输入和输出
نسخة الكود كما يلي:
يحاول {
//要求用户输入一个数字
var n = Number(prompt("请输入一个正整数", ""));
//假设输入是合法的,计算这个阶乘
var f = factorial(n);
//显示结果
alert(n + "!=" + f);
} catch (ex) {
//如果输入不合法,将执行这里的逻辑
document.write(ex); //告诉用户发送了什么。
}
这里的try/catch语句并不包含finally从句。尽管finally不像catch那样经常使用,但有时候它还是非常有用。然而,我们需要更详尽的解释它的行为。不管try语句块中的代码执行完成了多少,只要try语句中有一部分代码执行了,finally从句就会执行。它通常在try从句的代码后用于清理工作。
关注下面这个例子
نسخة الكود كما يلي:
يحاول {
print("Outer try running..");
يحاول {
print("Nested try running...");
throw "an error";
} catch (e) {
print("Nested catch caught " + e);
throw e + " re-thrown";
} أخيراً {
print("Nested finally is running...");
}
} catch (e) {
print("Outer catch caught " + e);
} أخيراً {
print("Outer finally running");
}
// Windows Script Host 作出该修改从而得出WScript.Echo(s)
function print(s) {
document.write(s);
}
الإخراج:
نسخة الكود كما يلي:
Outer try running..
Nested try running...
Nested catch caught an error
Nested finally is running...
Outer catch caught an error re-thrown
Outer finally running
7.其它语句类型。
本节讨论剩余的三种javascript语句:width,debugger和use strict
i.with语句
3.10讨论了作用域链(scope chain),一个可以按序检索的对象列表,通过它可以进行变量名的解析。width语句可以用来临时扩展作用域链:它具体有如下语法:
with (object)
إفادة
这条语句将object添加到作用域链头部,然后执行statement,最后把作用域链恢复到原始状态。
在严格模式下(5.7.iii)是禁止使用width的,在非严格模式下也是不推荐使用width语句的,尽可能的避免使用width语句。那些使用width语句的javascript非常难优化,而且比没有使用width的语句,它运行速度更慢。
在对象嵌套层次很深的时候,常会使用with语句来简化代码的编写。例如客户端javascript中,可能使用下面的这种表达式来访问表单的一个html元素
document.forms[0].address.value
如果这段代码多次出现,则可以使用with将form对象添加至作用域链的顶层。
نسخة الكود كما يلي:
with(document.forms[0]){
//直接访问表单元素
name.value="";
address.value="";
email.value ="";
}
这种方法简化了大量的输入,不用再为每个变量添加document.forms[0]前缀。这个临时对象挂载在作用域链上,当javascript需要解析诸如address标识符时,就会在这个对象中查找。当然,不使用with的语句代码可以写成这样。
نسخة الكود كما يلي:
var f = document.forms[0];
f.name.value = "";
f.adress.value = "";
f.email.value = "";
不要忘记,只有在查找标识符的时候才能用到作用域链,创建新的变量时候不使用它,看一下下面的代码:
نسخة الكود كما يلي:
with(o) x = 1;
如果对象o有一个属性x,那么这行代码给这个属性赋值1。如果o没有定义属性x,这段代码和不使用with的代码x=1是一模一样的。它给一个局部变量或者全局变量x赋值,或者创建全局对象的一个新属性。with语句提供了一种读取o属性的快捷方法,但并不会创建o的属性。
ii.debugger语句
debugger语句通常什么也不做。然而,在调试程序可用并运行的时候,javascript解释器将会(非必须)以调试模式运行。实际上,这条语句产生一个断点(breakpoint),javascript代码执行会停止在断点的位置,这时可用使用调速器输出变量的值,检查调用栈等。
例如加上调用函数f()的时候使用了未定义的参数,因此f()抛出一个异常,但无法定位到到底哪里出了异常。为了有助于调试这个问题,需要修改f():
نسخة الكود كما يلي:
function f(o){
if (o === undefined) debugger; //这段代码用来临时调试
console.log(1) //函数的其它部分
}
f();
这时候,当调用f()没有传入参数,程序将停止执行,这时候通过调用调速器检测调用栈并找出错误的原因。
在ECMAScirpt5中,debugger语句已经正式加入到专门语言里,但在很长的一段时间里,主浏览器的厂商已经将其实现了。注意,可用的调速器是远远不够的,debugger语句不会启动调试器。但如果调试器已经在运行,这条语句才会正在产生断点。例如,使用Firefox插件firebug,首先启动firebug,这样debugger语句才能工作。
ثالثا. "use strict"
“use strict”是ECMASCript5引入的一条指令。指令不是语句(但非常接近于语句),“use strict”和普通语句之前有两个重要区别:
1.它不包含任何语言的关键字,指令仅仅是一个包含一个特殊字符串直接量的表达式(可以是使用单引号也可以是双引号)。
2.它只能出现在脚本代码的开始或者函数体的开始、任何实体语句之前。但它不必一定出现在脚本的首行或者函数体内的首行。因为“use strict”指令之前之后或之前都可能有其它字符串直接量的表达式语句,并且javascript的具体实现可能将它们解析为解释器自有的指令。在脚本或者函数体内第一条常规语句之后,字符串直接量表达式语句只当做普通的表达式语句对待,它们不做指令解析,它们也没有任何副作用。
使用“use strict”指令的目的是说明(脚本或函数中)后续代码解析为严格代码(strict code)。如果顶层(不在任何函数内)代码使用了“use strict”指令,那么它们就是严格代码。如果函数体定义处的代码是严格代码或者函数体使用了“use strict”指令,那么函数体的代码也是严格代码。如果eval()调用所处的代码是严格代码或者eval()要执行的字符串使用了“scrict code”指令,则eval()内的代码是严格代码。
严格代码以严格模式执行。ECMAScript5中的严格模式是该语言的一个受限的子集。它修正了语言的重要缺陷,并提供健壮的差错功能和增强安全机制。严格模式和非严格模式区别如下(前三条尤其重要)
•严格模式中禁止使用with语句
•严格模式中,所有的变量要先声明,如果给一个未声明的变量、函数、函数参数、catch从句参数或全局的对象的属性赋值。就会抛出一个引用错误异常(在非严格模式中,这种隐式声明全局变量的方法是给全局变量新添加一个新属性)
•严格模式中,调用的函数(不是方法)中的一个this值是undefined。(在非严格模式中,调用的函数中的this值总是全局变量)。可以利用这种特性来判断javascript实现是否支持严格模式。
نسخة الكود كما يلي:
var hasStrictMode = (function() {
"use strict";
return this === undefined
}());
•同样,在严格模式中,当通过call()和apply()来调用函数时,其中的this值就是通过call()或apply()传第一个参数(在非严格模式中,null和undefined值被全局对象转换为对象的非对象值锁代替)
•在严格模式中,给只读属性赋值和给不可扩展的对象创建成员都将抛出一个类型错误异常(在非严格模式中,这些操作只是简单的操作失败,不会报错)。
•在严格模式中,传入eval()代码不能再调用辰星所在的上下文中声明变量或定义函数,在非严格模式中是可以这样做的。相反,变量和函数的定义是在eval()创建的作用域中,这个作用域在eval()返回时就弃用了。
•在严格模式中,函数里的arguments对象拥有传入函数值的静态副本。在非严格模式中,agreements对象具有“魔术般”的行为,arguments里的数组元素和函数都指向同一个值的引用。
•在严格模式中,当delete运算符后面跟随非法的标识符(比如变量、函数、函数参数时)将会抛出一个语法错误,(在非严格模式下,这种delete什么也没做,并返回false)
•在严格模式中,在一对象直接量中定义两个或多个同名属性将产生一个语法错误(非严格模式下不会报错)
•在严格模式下,不允许八进制整数直接量。(以0为前缀,而不是0x为前缀)在非严格模式中是允许直接八进制直接量的
•在严格模式下,标识符eval和arguments当做关键字,他们的值是不能更改的。不能给这些标识符赋值,也不能把它们声望为变量,用做函数名,用做函数参数或用做catch块的标识符。
•在严格模式中限制了对调用栈的检测能力,在严格的模式的函数中,arguments,caller和arguments.callee都会抛出一个类型错误异常。严格模式的函数同样具有caller和arguments属性,当访问这两个属性时抛出类型错误异常。
8.javascript语句小结:
javascript语句语法:
| إفادة | قواعد | يستخدم |
| استراحة | break[label]; | 退出最内侧循环或者退出switch语句,又或退出label指定的语句 |
| قضية | case expression: | 在switch语句标记一条语句 |
| تواصل المتابعة | continue [label]; | 重新开始最内层的循环或从新开始label指定的循环 |
| debugger | debugger; | 断点器调试 |
| تقصير | تقصير؛ | 在switch标记默认语句 |
| do/while | do statement while(expression); | while循环的一种替代形式 |
| فارغ | ؛ | 什么都不做 |
| ل | for(init;test;incr)statement | 一种简写的循环 |
| for/in | for(var in object)statement | 遍历一个对象属性 |
| وظيفة | function name([param[],...]){body} | 声明一个函数 |
| if/else | if (expr)statement1[else statement2] | 执行statement1或者statement2 |
| ملصق | label:statement | 给statement指定一个名字:label |
| يعود | return [expression]; | 从函数返回一个值 |
| يُحوّل | switch(expression){statements} | 用case或者“default:”语句标记多个分支语句 |
| يرمي | throw expression | 抛出异常 |
| يحاول | try {statements} [catch {hander satements}] [finally {cleanup satements}] | 捕获异常 |
| use strict | "use strict" | 对脚本和函数使用严格模式 |
| var | avr name=[=expr][,...] | 声明并初始化一个或多个变量 |
| بينما | while (expression) statement | 基本的循环结构 |
| مع | with(object) statement | 扩展作用域链(不赞成使用) |