اذهب إلى المحتوى

البحث في الموقع

المحتوى عن 'es6'.

  • ابحث بالكلمات المفتاحية

    أضف وسومًا وافصل بينها بفواصل ","
  • ابحث باسم الكاتب

نوع المحتوى


التصنيفات

  • الإدارة والقيادة
  • التخطيط وسير العمل
  • التمويل
  • فريق العمل
  • دراسة حالات
  • التعامل مع العملاء
  • التعهيد الخارجي
  • السلوك التنظيمي في المؤسسات
  • عالم الأعمال
  • التجارة والتجارة الإلكترونية
  • نصائح وإرشادات
  • مقالات ريادة أعمال عامة

التصنيفات

  • مقالات برمجة عامة
  • مقالات برمجة متقدمة
  • PHP
    • Laravel
    • ووردبريس
  • جافاسكربت
    • لغة TypeScript
    • Node.js
    • React
    • Vue.js
    • Angular
    • jQuery
    • Cordova
  • HTML
  • CSS
    • Sass
    • إطار عمل Bootstrap
  • SQL
  • لغة C#‎
    • ‎.NET
    • منصة Xamarin
  • لغة C++‎
  • لغة C
  • بايثون
    • Flask
    • Django
  • لغة روبي
    • إطار العمل Ruby on Rails
  • لغة Go
  • لغة جافا
  • لغة Kotlin
  • لغة Rust
  • برمجة أندرويد
  • لغة R
  • الذكاء الاصطناعي
  • صناعة الألعاب
  • سير العمل
    • Git
  • الأنظمة والأنظمة المدمجة

التصنيفات

  • تصميم تجربة المستخدم UX
  • تصميم واجهة المستخدم UI
  • الرسوميات
    • إنكسكيب
    • أدوبي إليستريتور
  • التصميم الجرافيكي
    • أدوبي فوتوشوب
    • أدوبي إن ديزاين
    • جيمب GIMP
    • كريتا Krita
  • التصميم ثلاثي الأبعاد
    • 3Ds Max
    • Blender
  • نصائح وإرشادات
  • مقالات تصميم عامة

التصنيفات

  • مقالات DevOps عامة
  • خوادم
    • الويب HTTP
    • البريد الإلكتروني
    • قواعد البيانات
    • DNS
    • Samba
  • الحوسبة السحابية
    • Docker
  • إدارة الإعدادات والنشر
    • Chef
    • Puppet
    • Ansible
  • لينكس
    • ريدهات (Red Hat)
  • خواديم ويندوز
  • FreeBSD
  • حماية
    • الجدران النارية
    • VPN
    • SSH
  • شبكات
    • سيسكو (Cisco)

التصنيفات

  • التسويق بالأداء
    • أدوات تحليل الزوار
  • تهيئة محركات البحث SEO
  • الشبكات الاجتماعية
  • التسويق بالبريد الالكتروني
  • التسويق الضمني
  • استسراع النمو
  • المبيعات
  • تجارب ونصائح
  • مبادئ علم التسويق

التصنيفات

  • مقالات عمل حر عامة
  • إدارة مالية
  • الإنتاجية
  • تجارب
  • مشاريع جانبية
  • التعامل مع العملاء
  • الحفاظ على الصحة
  • التسويق الذاتي
  • العمل الحر المهني
    • العمل بالترجمة
    • العمل كمساعد افتراضي
    • العمل بكتابة المحتوى

التصنيفات

  • الإنتاجية وسير العمل
    • مايكروسوفت أوفيس
    • ليبر أوفيس
    • جوجل درايف
    • شيربوينت
    • Evernote
    • Trello
  • تطبيقات الويب
    • ووردبريس
    • ماجنتو
    • بريستاشوب
    • أوبن كارت
    • دروبال
  • الترجمة بمساعدة الحاسوب
    • omegaT
    • memoQ
    • Trados
    • Memsource
  • برامج تخطيط موارد المؤسسات ERP
    • تطبيقات أودو odoo
  • أنظمة تشغيل الحواسيب والهواتف
    • ويندوز
    • لينكس
  • مقالات عامة

التصنيفات

  • آخر التحديثات

أسئلة وأجوبة

  • الأقسام
    • أسئلة البرمجة
    • أسئلة ريادة الأعمال
    • أسئلة العمل الحر
    • أسئلة التسويق والمبيعات
    • أسئلة التصميم
    • أسئلة DevOps
    • أسئلة البرامج والتطبيقات

التصنيفات

  • كتب ريادة الأعمال
  • كتب العمل الحر
  • كتب تسويق ومبيعات
  • كتب برمجة
  • كتب تصميم
  • كتب DevOps

ابحث في

ابحث عن


تاريخ الإنشاء

  • بداية

    نهاية


آخر تحديث

  • بداية

    نهاية


رشح النتائج حسب

تاريخ الانضمام

  • بداية

    نهاية


المجموعة


النبذة الشخصية

تم العثور على 7 نتائج

  1. فلنفترض أنك تريد تشغيل دالة اسمها bounceBall أربع مرات. كيف يمكنك ذلك؟ هل ستختار الطريقة التالية؟: function bounceBall() { // bounce the ball here } bounceBall() bounceBall() bounceBall() bounceBall() يمكن أن تكون الطريقة أعلاه مناسبة إذا كنت تريد تنفيذ الدالة بضع مرات. مالذي سيحدُث إن احتجت لتنفيذ الدالة bounceBall مئة مرة؟ الطريقة الأفضل في هذه الحالة هي استخدام تعليمة التكرار الحلقي for. تعليمة التكرار الحلقي for تنفّذ تعليمة التكرار الحلقي for كتلة من التعليمات البرمجية بعدد المرات التي تريد. في ما يلي مثال على تنفيذ الدالة bounceBall عشر مرات: for (let i = 0; i < 10; i++) { bounceBall() } تتكوّن التعليمة for من أربعة أجزاء: العبارة الابتدائية initialExpression الشرط condition عبارة الزيادة incrementalExpression والجملة statement for (initialExpression; condition; incrementExpression) { statement } ستحتاج عندما تريد تنفيذ تعليمة تكرار حلقي إلى جملة برمجية Statement. الجملة هي كتلة الشفرة البرمجية التي تريد تنفيذها مرات عدّة. يمكنك كتابة أي شفرة ترغب بها مهما كان عدد أسطرها، كما يمكنك استخدام دوال. تأخذ التعليمة for الصيغة التالية عند استخدام الدالة bounceBall في الجزء الخاصّ بالجملة: for (initialExpression; condition; incrementExpression) { bounceBall() } ستحتاج كذلك إلى تعريف عبارة ابتدائية Initial expression تبدأ بها تعليمة التكرار الحلقي. هذا هو الجزء الذي تعرّف فيه متغيرا. من المتعارف عليه تسمية المتغير الابتدائي في تعليمة for بالحرف i وإعطاؤه القيمة 0. هكذا تبدو صيغة for عند تحديد عبارتها الابتدائية: for (let i = 0; condition; incrementExpression) { bounceBall() } نزيد قيمة المتغيّر (i في مثالنا) - أو ننقُصه - بعد تنفيذ الحلقة التكرارية لأول مرة، وذلك عن طريق عبارة الزيادة Incremental expression. لزيادة قيمة المتغير i بواحد نعيد إسناده بحيث يُصبح يساوي i + 1 أي بالعبارة i = i + 1. تُختَصر العبارة i = i + 1على ++i والتي يكثُر استخدامها في حلقات التكرار. لنقص قيمة المتغير i بواحد نعيد إسناده بحيث يُصبح يساوي i - 1، أي بالعبارة i = i - 1. تُختَصر العبارة i = i - 1 على --i. بالعودة إلى المثال مع الدالة bounceBall فإننا زدنا المتغيّر i في كل مرة بواحد. تصبح صيغة التعليمة for على النحو التالي: for (let i = 0; condition; i++) { bounceBall() } لكن… هل يجدُر بي زيادة قيمة المتغيّر أم النقص منها؟ توجد الإجابة في الجزء الأخير من تعليمة التكرار الحلقي for وهو الشرط. في حالة تحقّق الشرط - أي أن قيمته تساوي true - فإن الجملة الموجودة في التعليمة for تُنفَّذ وإلا فلا. ينفّذ مفسر جافاسكريبت عبارة الزيادة incrementalExpression مباشرة بعد تنفيذ الجملة statement ثم يتحقّق مجدّدًا من أن قيمة الشرط تساوي true فإن كان الأمر كذلك نفّذ الجملة statement مرة أخرى. يعيد المفسّر الكرة إلى أن تصبح قيمة الشرط false. حينها يتجاوز الحلقة التكرارية وينفّذ الشفرة التي تليها. إن لم تكن تريد تنفيذ الحلقة فيمكنك جعل قيمة الشرط مساوية لـ false منذ البداية: // لن تُنفَّذ الحلقة التكرارية التالية نظرا لأن قيمة الشرط تساوي false for (let i = 0; i < 0; i++) { bounceBall() const timesBounced = i + 1 console.log('The ball has bounced ' + timesBounced + ' times') } // ستُنفّذ الشفرة التالية فقط console.log('next line of code') ستكون نتيجة تنفيذ الشفرة أعلاه على النحو التالي: next line of code عندما تريد تنفيذ الحلقة التكرارية مرتين فستحتاج إلى تغيير الشرط بحيث تكون قيمته false بعد تنفيذ عبارة الزيادة مرتين: // ستُنفّذ الحلقة التكرارية التالية مرتين for (let i = 0; i < 2; i++) { bounceBall() const timesBounced = i + 1 console.log('The ball has bounced ' + timesBounced + ' times')") } console.log('next line of code') النتيجة: The ball has bounced 1 times The ball has bounced 2 times next line of code أما إذا أردت تشغيل الحلقة عشر مرات فسيتوجّب عليك تغيير الشرط بحيث تصبح قيمته false بعد تنفيذ عبارة الزيادة عشر مرات. // ستُنفّذ الحلقة التكرارية التالية عشر مرات for (let i = 0; i < 10; i++) { bounceBall() const timesBounced = i + 1 console.log('The ball has bounced ' + timesBounced + ' times')") } console.log('next line of code') النتيجة: الحلقات غير المحدودة Infinite loops نجد أنفسنا أمام حلقات غير محدودة عندما تكون قيمة الشرط في الحلقة التكرارية for مساوية دائما لـtrue، ممّا يتسبّب في تجمّد التبويب أو المتصفّح ونحتاج بالتالي لإغلاقه وإعادة تشغيله. استخدام الحلقات التكرارية مع المصفوفات Arrays في الواقع لن تحتاج كثيرا لاستخدام الحلقات التكرارية لتنفيذ دالة عشر مرات كما فعلنا مع الدالة bounceBall السابقة. أغلب استخدامات الحلقات التكرارية هو مع المصفوفات أو الكائنات Objects. يتمثّل التكرار عبر المصفوفة في المرور مرة واحدة على كل عنصُر في المصفوفة. بالإمكان استخدام طول المصفوفة (التابع length) في الجزء الخاص بالشرط من تعليمة التكرار. const fruitBasket = ['موزة', 'تفاحة', 'إجاصة'] // fruitBasket.length is 3 for (let i = 0; i < fruitBasket.length; i++) { console.log("توجد " + fruitBasket[i] + " في السلة") } النتيجة: توجد موزة في السلة توجد تفاحة في السلة توجد إجاصة في السلة هناك طريقة بديلة وهي استخدام عبارة نقص بدلًا من عبارة الزيادة، وذلك بالبدء من نهاية المصفوفة في العبارة الابتدائية ضمن تعليمة التكرار: for (let i = fruitBasket.length - 1; i >= 0; i--) { console.log("توجد " + fruitBasket[i] + " في السلة") } النتيجة (لاحظ الفرق): توجد إجاصة في السلة توجد تفاحة في السلة توجد موزة في السلة المرور على المصفوفات بالحلقة for of هناك طريقة ثالثة - أفضل بكثير - للمرور عبر مصفوفة، وهي استخدام تعليمة التكرار الحلقي for...of وهي تعليمة جديدة من إضافات المعيار ES6. تُكتَب التعليمة بالصيغة التالية const fruitBasket = ['موزة', 'تفاحة', 'إجاصة'] for (let fruit of fruitBasket) { console.log("توجد " + fruit + " في السلة") } النتيجة: توجد موزة في السلة توجد تفاحة في السلة توجد إجاصة في السلة يُفضَّل استخدام التعليمة for ...of بدلا من الطريقة التقليدية لاستخدام تعليمة التكرار الحلقي for عند التعامل مع المصفوفات فهي تمرّ على المصفوفة لمرة واحدة فقط، كما لا تحتاج إلى طول المصفوفة؛ ممّا يجعل قراءة الشفرة وصيانتها أيسر بكثير. يمكن استخدام التعليمة for ...of مع أي كائن لديه الخاصيّة Symbol.iterator. إن طبعت مصفوفة فارغة باستخدام التعليمة console.log فسترى أن لديها خاصيّة باسم Synmbol.iterator (ضمن المفتاح _proto_). العمليات المنطقية في الحلقات التكرارية يمكنك استخدام if/else أو أي عمليات منطقية أخرى داخلة حلقة for التكرارية. فلنفترض مثلا أن لديك مصفوفة بمجموعة من الأعداد وتريد إنشاء مصفوفة ثانية تتضمّن أعداد المصفوفة الأولى التي تصغُر 20. حتى تصل إلى هدفك فيجب أن تمرّ أولا على عناصر المصفوفة الأولى بحلقة for: const numbers = [25, 22, 12, 56, 8, 18, 34]; for (let num of numbers) { // سنكمل التعليمات بعد قليل } ثم نتحقّق ما إذا كان العنصُر الذي نمرّ عليه يقل عن 20. تصبح الشفرة كالتالي: const numbers = [25, 22, 12, 56, 8, 18, 34]; for (let num of numbers) { if (num < 20) { // نكمل بعد قليل } } إذا كان العنصُر أصغر من 20 نضيفه إلى مصفوفة أخرى. نستعمل التابع push لهذا الغرض. تصبح الشفرة كالتالي (smallerThan20 هو اسم المصفوفة الثانية): const numbers = [25, 22, 12, 56, 8, 18, 34]; let smallerThan20 = [] for (let num of numbers) { if (num < 20) { smallerThan20.push(num) } } ترجمة - بتصرّف - للمقال Understanding for loops لصاحبه Zell Liew.
  2. تخيّل أنك تعيش في قرية لا تتوفّر على شبكة مياه. تحتاج، للحصول على الماء، لأخذ سطل فارغ والذهاب إلى بئر وسط القرية وسحب المياه من البئر ثم العودة إلى المنزل. تعاود الكرة مرات عدّة في اليوم، حسب حاجتك للمياه. سيكون شرحُ ما تفعله بالتفصيل في كل مرة تُسأل فيها عن الأمر مضيعة للوقت؛ لذا بدلا من أن تقول “آخذ سطلا فارغا وأذهب إلى البئر وسط المدينة، ثم أسحب دلوا من الماء من البئر وأفرغه في السطل وأعود”، بدلا من ذلك تجيب اختصارا “أجلب الماء”. لقد أنشأت بهذه الإجابة دالة برمجية Function. تعريف الدوالّ الدالة هي كتلة من الأسطر البرمجية التي تنفّذ مجموعة من المهامّ وفق ترتيب محدَّد، مثلا: “آخذ السطل، أذهب إلى البئر، أسحب الماء منه وأعود”. تُعرَّف الدالة بالصياغة التالية: function functionName (parameters) { // نفّذ المهام هنا } function هي الكلمة المفتاحية التي تخبر جافاسكريبت أنك بصدد الإعلان عن دالة. functionName هو اسمُ الدالة. في المثال أعلاه فإن اسم الدالة يمكن أن يكون drawWater (اغرف الماء). يمكن أن يكون اسمُ الدالة أيا اسم تختاره ما دام يحترم شروط أسماء المتغيّرات، أي: أن يكون كلمة واحدة، أن يتكوّن فقط من حروف لاتينية (a-z, A-Z)، أرقام (0-9) أو علامة تسطير سفلي _. أن لا يكون كلمة محجوزة Reserved keywords في جافاسكريبت. المعاملات Parameters هي مجموعة من المتغيّرات تفصل بينها فاصلة لاتينية , تريد تعريفها للاستخدام داخل الدالة. المعاملات اختيارية ويمكن تعريف دالة دون معاملات. استخدام الدوالّ يمكن استخدامُ الدالة بعد تعريفها. تدلّ العبارات “استخدام الدالة”، “تنفيذ الدالة” أو “استدعاء الدالة” على الشيء ذاته. لاستدعاء الدالة نكتُب اسمَها متبوعا بقوسين (). في ما يلي مثال نعرّف فيه دالة باسم sayHello ثم نستخدمها: // تعريف الدالة function sayHello () { console.log('Hello world!') } // استدعاء الدالة sayHello() ينتُج عن تنفيذ الدالة بالطريقة المشروحة أعلاه طباعةُ العبارة Hello world. الإزاحة The indentation يجب إزاحة جميع الأسطُر البرمجية الموجودة في كتلة، أي تقع بين قوسين معكوفين {}، إلى اليمين. هذه الممارسة مهمّة جدا وتساعد في تسهيل قراءة الشفرة البرمجية وصيانتها، وتمكّنك بنظرة واحدة معرفة أن التعليمة console.log('Hello world') هي جزء من الدالة sayHello: function sayHello () { // تعليمة console.log أدناه مزاحة قليلا إلى اليمين وبالتالي فهي جزء من الدالة sayHello console.log('Hello world!') } يمكنك استخدام مسافتيْن (زر المسافة في لوحة المفاتيح مرتيْن) أو مفتاح الجدولة في لوحة المفاتيح Tab لإزاحة التعليمات في الشفرة. يفضّل بعض المطوّرين مفتاح الجدولة في ما يُفضّل آخرون المسافتين. استخدم أيهما تراه مناسبا، مع التأكد من استخدام نفس طريقة الإزاحة في كامل الشفرة. المعاملات تأخذ معظم الدوال معاملات، وهي عبارة عن سلسلة من المتغيّرات تفصل بينها فاصلة ,، تُعرَّف لتُستخدَم داخل الدالة. يمكنك تعريف معاملات بالعدد الذي تريد. function functionName(param1, param2, param3) { // نفّذ المهام هنا } تُسنَد القيم إلى المعاملات بتمريرها بين قوسين إلى الدالة في سلسلة تفصل بينها فاصلة ,. تُسمَّى القيم المُمرَّرة إلى الدالة بالمعطيات Arguments. يُسنَد المعطى الأول إلى المعامل الأول، والمعطى الثاني إلى المعامل الثاني وهكذا: functionName('arg1', 'arg2') فلنشرح الأمر أكثر بمثال. فلنقل إنك تريد تعريف دالة باسم sayName وظيفتها تسجيل الاسم الشخصي والاسم العائلي لشخص. تبدو الدالة بالشكل التالي: function sayName(firstName, lastName) { console.log('اسمك الشخصي هو ' + firstName) console.log('اسمك العائلي هو ' + lastName) } تُعرّف الدالة معاملين هما firstName وlastName. فلنفترض أن الاسم الشخصي هو “محمد” والاسم العائلي هو “عيسى”. لجعل الدالة تعمل على النحو المرغوب نمرّر لها المعطييْن محمد وعيسى كالتالي: sayName('محمد', 'عيسى') نحصُل بعد تنفيذ الدالة بالطريقة أعلاه على النتيجة التالية: اسمك الشخصي هو محمد اسمك العائلي هو عيسى عند تعريف معامل أثناء تعريف الدالة ثم استخدام الدالة دون تمرير معطيات فإن المعامل سيأخذ القيمة “غير معرَّف” undefined: sayName() النتيجة: // اسمك الشخصي هو undefined // اسمك العائلي هو undefined جملة إرجاع Return statement يمكن أن تحتوي الدوال على جملة إرجاع تتكوَّن من الكلمة المفتاحية return متبوعة بقيمة. function functionName () { return 'some-value' } عندما يجد مفسّر جافاسكريبت هذه الجملة فإنه يتوقّف عن تنفيذ التعليمات الموالية في الدالة ويُرجع قيمة (يمرّر القيمة المعنية إلى الشفرة التي استدعت الدالة): function get2 () { return 2 console.log('blah') // لن تُنفذ هذه التعليمة } const results = get2() console.log(results) // تُطبع القيمة 2، وهي القيمة المُرجَعة من الدالة // ملحوظة: لن تُطبَع القيمة 'blah' إن كانت الكلمة المفتاحية return متبوعة بعبارة بدلا من قيمة حرفية فإن مفسّر جافاسكريبت يحدّد نتيجة تنفيذ العبارة ثم يُرجِع القيمة الناتجة. تذكّر أن القيم التي يمكن لجافاسكريبت تمريرها هي إما أنواع أصلية (مثل سلاسل المحارف، الأعداد والقيم المنطقية) أو كائنات Objects (دوالّ، مصفوفات وكائنات). كلّ ما عدا ذلك يجب تقويمه (معرفة قيمته) قبل التمرير إلى الشفرة التي استُدعِيت فيها الدالة. تسلسل تنفيذ التعليمات عند استدعاء الدوال قد تكون الدوال صعبة الفهم على المبتدئين. سنرى، للتأكد من فهم الدوال تماما، مالذي يحدُث عند تعريف دالة واستدعائها. هذه المرة سنتناول كل خطوة على حدة. في ما يلي الشفرة التي سنعمل على تفكيك عملها: function add2 (num) { return num + 2 } const number = add2(8) console.log(number) // تطبع العدد 10 أولا وقبل كل شيء، نحتاج إلى تعريف الدالة قبل أن نتمكّن من استخدامها. يرى مفسّر جافاسكريبت في السطر الأول الكلمة المفتاحية function فيعرف أن الكلمة التي تليها، أي add2 هي اسم الدالة. بعد تعرّف المفسّر على اسم الدالة يتجاوز الشفرة الموجودة بين معكوفين التي تلي الاسم، لأنه حتى الآن لم يُطلب منه تنفيذ الدالة. في السطر التالي يجد المفسّر أننا عرّفنا متغيّرا ذا قيمة ثابتة اسمه number وأسندنا له القيمة add2(8). بما أن الطرف الموجود على يمين علامة الإسناد = هو دالة، فإن جافاسكريبت سيحتاج إلى تنفيذ الدالة قبل إسناد قيمتها إلى المتغيّر. يعيّن المفسّر القيمة 8 لتكون معطى للمعامل num في الدالة ويبدأ بتنفيذ الدالة. عند الدخول إلى كتلة الدالة (الشفرة بين قوسين معكوفين بعد اسم الدالة) يجد المفسّر أمامه الكلمة المفتاحية return متبوعة بعبارة num + 2، فيعرف أنه سيحتاج إلى معرفة نتيجة العبارة قبل الخروج من الدالة. بما أن قيمة num هي 8 فإن num + 2 يجب أن تساوي 10. عرف المفسّر الآن قيمة العبارة num + 2 ويمكنه بالتالي إرجاع القيمة المُتحصَّل عليها إلى الشفرة التي استدعت الدالة. فيضع القيمة المرجعة مكان الدالة فتُصبح 10 مكان add2(8). يُنشئ المفسّر، بعد اكتمال تنفيذ الطرف الأيمن من عملية إسناد المتغيّر والحصول على نتيجتها، متغيّرا بالاسم المذكور number ويعطيه القيمة 10. هكذا يُقرأ تسلسل تنفيذ التعليمات في الدوال. رفع الدوال Hoisting تُنقَل الدوال تلقائيا عند تعريفها بالطريقة التي رأيناها سابقا إلى أعلى الشفرة البرمجية. بمعنى أن طريقتيْ التعريف والاستخدام التاليّتيْن متكافئتان تماما: function sayHello () { console.log('Hello world!') } sayHello() // تُحوّل الشفرة التالية عند التنفيذ تلقائياإلى الشفرة أعلاه sayHello() function sayHello () { console.log('Hello world!') } قد يؤدّي الرفع التلقائي للدوال إلى الإرباك؛ لذا من المناسب تعريف الدوال دائما قبل استخدامها. تعريف الدوال بعبارات الدوال Function expressions توجد طريقة ثانية لتعريف الدوال، وهي عبارات الدوال. يُعرَّف في هذه الحالة متغيّر ويُسنَد إلى دالة غير مسمّاة (دالة مجهولة الاسم Anonymous funvtion) const sayHello = function () { console.log('This is declared with a function expression!') } ينبغي الانتباه إلى أن الدوال المُعرَّفة بعبارات لا تُنقَل تلقائيا إلى أعلى الشفرة. تُنتج الشفرة التالية خطأ: sayHello () // Error, sayHello is not defined const sayHello = function () { console.log('this is a function!') } تُستخدَم الدوال المُعرَّفة بعبارات كثيرا في توابع الكائنات Object methods وفي الدوالّ السهمية Arrow functions. خاتمة الدالة هي كتلة من التعليمات البرمجية تنفَّذ وفق ترتيب محدَّد على منوال: خذ سطلا فارغا، اذهب إلى البئر، اسحب الماء ثم عُد إلى المنزل. تُستدعى الدالة بإضافة قوسين () بعد اسمها. يمكنك عند استدعاء الدالة إضافة معطيات جديدة بذكرها بين القوسين مفصولة بفاصلة ,. يمكن لكلّ دالة أن تحوي جملة إرجاع تعيد قيمة إلى الشفرة التي استُدعِيت منها. يُفضَّل دائما تعريف الدوال قبل استخدامها. ترجمة - بتصرّف - للمقال Understanding JavaScript Functions لصاحبه Zell Liew.
  3. فلنقل إنك تسير في شارع مكتظ وسط المدينة، تتأهب للمرور في مفترق طرق وفي هذه الأثناء انتقلت الإشارة الضوئية الخاصّة بالراجلين إلى اللون الأحمر. مالذي ستفعله؟ تتوقف… أليس كذلك؟ ماذا لو تبدّل اللون إلى الأخضر بعد ذلك؟ تعود إلى المشي. يمكننا اعتماد نفس المبدأ في الشفرات البرمجية. يبدو الأمر كما لو أنك تقول “إن أصبح لون الإشارة أحمر فيجب عليك التوقف وإلا استمرّ في المشي”. هذا بالضبط هو عمل الجملة if/else (إنْ… وإلا) في جافاسكريبت. الجملة if/else تساعد الجملة if/else بالتحكّم في ما يفعله برنامجك في حالات محدّدة. تأخذ الصيغة التالية: if (condition) { // افعل شيئا هنا } else { // افعل شيئا مغايرا هنا } يخبر الشرط Condition الجملة if/else مالذي يجب عليها التحقّق منه قبل الاستمرار. إذا كانت قيمة الشرط صحيحة (تساوي true) فإن جافاسكريبت سينفّذ الشفرة الموجودة داخل كتلة if. أما إذا كانت قيمة الشرط غير صحيحة (أي false) فإن الشفرة الموجودة في الكتلة else هي ما سيُنفّذ. بالعودة إلى مثال الإشارة الضوئية أعلاه فإن الأمر سيأخذ الصيغة التالية: if (الإشارة حمراء) { // توقّف عن المشي } else { // استمرّ في المشي } إن احتجت للتحقّق من شروط عدّة فيمكنك إضافة else if بين كتلتيْ if وelse. متى ستحتاج لشرط ثان؟ فلنقل إنك تمرّ عبر طريق صغيرة. إن لم تكن هناك سيارات فهل ستستمر في الانتظار إلى أن يتغيّر لون الإشارة الضوئية؟ على الأرجح ستواصل طريقك. بترجمة الحالة أعلاه إلى شفرة برمجية نجد التالي: if (الإشارة حمراء) { // توقّف عن المشي } else if (توجد سيارات) { // توقّف عن المشي } else if (شرط آخر) { // افعل أمرا آخر } else { // أمر أخير } إذا كان الشرط الأول في الشفرة أعلاه متحقّقا فإن مفسّر جافاسكريبت ينفّذ الشفرة الموجودة ضمن كتلة if، أما إذا كان هذا الشرط غير متحقّق فإن المفسّر ينظُر في الشرط الموجود في جملة else if الموالية لمعرفة ما إذا كان متحقّقا… وهكذا إلى إن يمرّ عبر جميع جمل else if. يعتمد مفسّر جافاسكريبت على أساسيْن لمعرفة تحقّق الشرط من عدمه: عوامل المقارنة Comparison operators. القيم الصحيحة و القيم الخاطئة. عوامل المقارنة توجد أربعة عوامل أساسية للمقارنة: “أكبر من” < أو “أكبر من أو يساوي”=< “أصغر من” > أو “أصغر من أو يساوي”=> “يساوي تماما” === أو “يساوي” == “يختلف تماما” ==! أو “يختلف” =! النوعان الأولان من عوامل المقارنة واضحان ويستخدمان لمقارنة الأعداد: 24 > 23 // صحيح 24 > 24 // خاطئ 24 >= 24 // صحيح 24 < 25 // صحيح 24 < 24 // خاطئ 24 <= 24 // صحيح النوعان التاليّان يُستخدمان لمقارنة تساوي شيئين: 24 === 24 // صحيح 24 !== 24 // خاطئ إلا أنه يوجد فرق بين “يساوي تماما” === و “يساوي” ==، وبين “يختلف تماما” == ! و “يختلف” =! '24' === 24 // خاطئ '24' == 24 // صحيح '24' !== 24 // صحيح '24' != 24 // خاطئ يتّضح من المثال أعلاه أن مقارنة العدد 24 بسلسلة المحارف 24 تعطي نتيجة خاطئة عند استخدام العامل “يساوي تماما” (===) بينما تعطي نتيجة صحيحة عند استخدام العامل “يساوي” (==). لماذا هذا الاختلاف؟ فلنر الفرق بين “يساوي تماما” و “يساوي”. الفرق بين === و == (و بين ==! و =!) أنواع البيانات Data types في جافاسكريبت ليست صرامة بل متساهلة، عكس لغات أخرى. يعني هذا أننا لا نهتم عندما نعرّف متغيّرا بنوع البيانات الذي ستأخذه قيمة هذا المتغيّر. يمكنك تعريف أي متغيّر وسيتكفّل مفسّر جافاسكريبت بالتعامل مع نوع البيانات الخاصّ بقيمة المتغيّر: const aString = 'Some string' const aNumber = 123 const aBoolean = true عند استخدام العامل “يساوي تماما” (===) أو “يختلف تماما” (==!) فإن مفسّر جافاسكريبت يأخذ أنواع بيانات قيم المتغيّرات بالحسبان؛ لهذا السبب فإن سلسلة المحارف 24 تختلف عن العدد 24. '24' === 24 // خطأ '24' !== 24 // صحيح أما عند استخدام العامل “يساوي” (==) أو “يختلف” (=!) فإن مفسّر جافاسكريبت يحوّل نوع البيانات بحيث يتساوى نوع طرفيْ المقارنة قبل أن ينظُر في القيمة. عمومًا، يحاول مفسّر جافاسكريبت تحويل جميع أنواع البيانات إلى أعداد عند استخدام عوامل المقارنة (ما عدا ===و==!). تُحوَّل سلسلة المحارف 24 في المثال أدناه إلى العدد 24 قبل المقارنة. هذا هو السبب الذي يجعل سلسلة المحارف 24 تساوي العدد 24 عند استخدام العامل ==: '24' == 24 // صحيح '24' != 24 // خاطئ يمكن كذلك تحويل القيم المنطقية (true وfalse) إلى أعداد، وعندها تصبح قيمة true تساوي 1 وfalse تساوي 0: 0 == false // صحيح 1 == true // صحيح 2 == true // خاطئ يعدّ التحويل التلقائي الذي يقوم به مفسّر جافاسكريبت أثناء استخدام عوامل المقارنة أحد أكثر الأسباب شيوعا لصعوبة التعرف على العلل Bugs أثناء تطوير البرامج؛ لذا استخدم دوما عوال المقارنة التامّة (=== أو==!). دورة تطوير التطبيقات باستخدام لغة Python احترف تطوير التطبيقات مع أكاديمية حسوب والتحق بسوق العمل فور انتهائك من الدورة اشترك الآن مقارنة الكائنات والمصفوفات حاول أن تقارن بين الكائنات أو بين المصفوفات بالعامل === أو == وستجد نتيجة مفاجئة: const a = { isHavingFun: true } const b = { isHavingFun: true } console.log(a === b) // خطأ: الكائن a مختلف تماما عن الكائن b console.log(a == b) // خطأ: الكائن a مختلف عن الكائن b الكائنان a وb في المثال أعلاه يبدوان متشابهين تماما: كلاهما كائن ويحويان نفس القيم. الأمر الغريب هو أن المقارنة a === b ترجع دائما قيمة خاطئة false؛ لماذا؟ فلنفترض أنكَ وأخاك (أو أنكِ وأختك) توأم. تبدو مشابهًا تمامًا لأخيك: نفس لون الشعر، نفس شكل الوجه، نفس الثياب؛ كيف يمكن التفريق بينك وأخيك؟ سيكون الأمر صعبًا. لدى كل كائن في جافاسكريبت بطاقة تعريف (هوية) تُسمّى مرجع الكائن Object’s reference. عند استخدام عوامل المقارنة للتحقّق من تساوي كائنين في جافاسكريبت فإنك تطلُب من المفسر التحقّق ممّا إذا كان للكائنيْن نفسُ المرجع (بطاقة التعريف). ليس غريبًا الآن أن تكون قيمة الشرط a === b في المثال أعلاه مساوية لـfalse. فلنعدّل قليلاً على المثال ونسند a إلى b: const a = { isHavingFun: true } const b = a تصبح نتيجة المقارنة a === b الآن مساوية لـ true (أي أن الكائنين متساويان). السبب في ذلك هو أن الكائنين a وb لديهما الآن نفس المرجع. console.log(a === b) // true القيم الصحيحة و القيم الخاطئة إن وضعت اسم متغيّر (hasApples - بمعنى لديه تفاح - في المثال أدناه) مكان الشرط في جملة if/else فإن مفسّر جافاسكريبت سيبحث عن قيمة صحيحة أو قيمة خاطئة. const hasApples = 'true' if (hasApples) { // تناول تفاحة } else { // اشتر تفاحا } القيم الخاطئة هي قيم تأخذ القيمة false عند تحويلها إلى نوع البيانات المنطقية Boolean. توجد ست قيم خاطئة في جافاسكريبت: false undefined null 0 (العدد صفر) "" (سلسلة محارف فارغة) NaN على الجانب الآخر، القيم الصحيحة هي تلك التي تأخذ القيمة true بعد تحويلها إلى بيانات منطقية. في حالة الأعداد فإن أية قيمة مغايرة للصفر تُحوَّل إلى قيمة صحيحة. تُشجّع جافاسكريبت على استخدام التحويل التلقائي إلى قيم صحيحة وقيم خاطئة لكونها تجعل من الشفرة البرمجية أقصر وأسهل فهما. إن أردت على سبيل المثال التحقّق من أن سلسلة محارف فارغة فيمكنك استخدام هذه السلسلة مباشرة في شرط الجملة if/else: const str = '' if (str) { // سلسلة المحارف غير فارغة } else { // سلسلة المحارف فارغة } خاتمة تُستخدم الجمل الشرطية if/else للتحكّم في عمل البرامج في حالات محدّدة؛ فتسمح لك بتحديد ما إذا كان يتوجب عليك الاستمرار في المشي أو الانتظار لتجاوز مفترق طرق. توجد طريقتان للتحقّق من الشروط في جافاسكريبت: عوامل المقارنة القيم الصحيحة والقيم الخاطئة ترجمة - تصرّف - للمقال Understanding if/else statements لصاحبه Zell Liew.
  4. تطوّرت لغة البرمجة جافاسكريبت كثيرا خلال السنوات القليلة الماضية. إن كنت تتعلّم جافاسكريبت في 2017 دون أن تتعامل مع الإصدار ES6 فأنت تفوّت الفرصة لاستغلال طريقة يسيرة لقراءة شفرات جافاسكريبت وكتابتها. لا تقلق إن لم تكن خبيرًا في جافاسكريبت، فليس ضروريًا أن تكون ماهرًا جدًا في جافاسكريبت للاستفادة من الامتيازات التي يمنحها الإصدار ES6. سنتعرّف في هذا المقال على ميزات يقدّمها ES6 ويمكنك استخدامها يوميًا للتعوّد على الصياغة الجديدة لجافاسكريبت. الميزات الجديدة في ES6 يقدّم الإصدار ES6 الكثير من الميزات الجديدة ويضيفها إلى جافاسكريبت. يمكنك التعرّف على أهم هذه الميزات بقراءة المقاليْن التاليّيْن: ما الجديد في الإصدار القادم من جافاسكريبت (ECMAScript 6) - الجزء الأول. ما الجديد في الإصدار القادم من جافاسكريبت (ECMAScript 6) - الجزء الثاني. ليس ضروريًا أن تعرف كلّ ما يقدّمه الإصدار الجديد من أول وهلة. سأتشارك معك في هذا المقال ثلاث ميزات للبدء بها واستخدامها: الكلمتان المفتاحيّتان let وconst. الدوال السهمية Arrow functions. بالمناسبة؛ تدعم أغلب المتصفّحات الحديثة - مثل Edge، الإصدارات الحديثة من فيرفكس وكروم - ES6 جيّدًا دون الحاجة لأدوات إضافية مثل Webpack. بالنسبة للمتصفحات القديمة نسبيًا توجد مكتبات بديلة Polyfills يوفّرها مجتمع جافاسكريبت؛ ابحث عنها. ننتقل بعد التقديم إلى الميزة الأولى. الكلمتان المفتاحيّتان let وconst تُستخدَم الكلمة المفتاحية var عادة في ES5 (الإصدار القديم من جافاسكريبت) لتعريف المتغيّرات. يُمكن في ES6 إبدال var بـ let وconst؛ وهما كلمتان مفتاحيّتان لهما تأثير معتبر وتساعدان في تسهيل كتابة الشفرات البرمجية. نبدأ بإلقاء نظرة على الفرق بين let وvar لنفهم لماذا let وconst أفضل. الفرق بين let وvar بما أننا معتادون على var فسنبدأ أولاً بها. يمكننا تعريف المتغيرات بـvar ثم استخدامها بعد ذلك في أي مكان من النطاق Scope الحالي. var me = 'Zell' console.log(me) // Zell عرّفنا في المثال السابق متغيّرا عامًّا Global باسم me. نستطيع استخدام المتغيّر العام me في دالة على النحو التالي: var me = 'Zell' function sayMe () { console.log(me) } sayMe() // Zell إلا أن العكس ليس صحيحًا. إن عرّفنا متغيّرًا باسم me داخل الدالة فلن يمكننا استخدامه خارجها وسيظهر خطأ في التنفيذ: function sayMe() { var me = 'Zell' console.log(me) } sayMe() // Zell console.log(me) // Uncaught ReferenceError: me is not defined يمكننا القول إذًا إن var ذات نطاق معرَّف على مستوى الدالة Function-scoped. يعني هذا أن أي متغيّر عُرِّف داخل دالّة بـvar لن يوجد خارج هذه الدالة. إن عُرِّف المتغيّر بـvar خارج الدالة فسيكون موجودًا في النطاق الخارجي: var me = 'Zell' // النطاق العام function sayMe () { var me = 'Sleepy head' // نطاق الدالة المحلّي console.log(me) } sayMe() // Sleepy head console.log(me) // Zell بالنسبة للكلمة المفتاحية let فهي ذات نطاق معرَّف على مستوى الكتلة Block-scoped. يعني هذا أنه عند إنشاء متغيّر بـlet فستكون موجودة داخل كتلة let. لكن.. ما هي “الكتلة”؟ تُعرَّف الكتلة في جافاسكريبت بأنها كل ما يوجد بين قوسين معكوفين. في ما يلي أمثلة على الكتل: { // نطاق كتلة جديدة } if (true) { // نطاق كتلة جديدة } while (true) { // نطاق كتلة جديدة } function () { // نطاق كتلة جديدة } الفرق بين المتغيرات المعرَّفة على مستوى الدالة وتلك المعرَّفة على مستوى الكتلة كبير جدًا. إن استخدمت متغيّرات معرَّفة على مستوى الدالة فمن السهل تغيير قيمة المتغيّر دون قصد. في ما يلي مثال: var me = 'Zell' if (true) { var me = 'Sleepy head' } console.log(me) // 'Sleepy head' يظهر في المثال السابق أن المتغيّر me يأخذ القيمة “Sleepy head” بعد الخروج من كتلة التعليمة if. ربما لا تواجه مشاكل على النحو المذكور في المثال أعلاه لأنك لا تعرّف متغيّرات بنفس الاسم؛ لكن إن كنت ممّن يستخدم var في حلقات for التكرارية فربما تصادف بعضًا من الأمور الغريبة التي تحدث بسبب آلية التعامل مع نطاقات المتغيّرات في جافاسكريبت. فلنتأمل الشفرة التالية التي تطبع قيمة المتغيّر i أربع مرات ثم تطبعها من جديد مع استخدام الدالة setTimeout التي تنتظر 1000 ملي ثانية (أي ثانية واحدة) قبل تنفيذ التعليمة console.log: for (var i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000) }; مالذي تتوقّعه من الشفرة السابقة؟ نلاحظ أن المتغيّر i أخذ القيمة 5 في مرات تنفيذ الدالة setTimeout الأربع. كيف أصبحت قيمة i تساوي 5 في كل مرة تُنفّذ فيها الدالة setTimeout؟ يعود السبب في ذلك إلى أن قيمة المتغيّر i أصبحت تساوي 5 حتى قبل تنفيذ الدالة setTimeout لأول مرة. وبما أن var تعرّف المتغيّر على مستوى الدالة فإن i هو نفس المتغيّر الذي تعمل عليه الحلقة التكرارية والذي أصبح يساوي 5 أثناء انتظار setTimeout لانقضاء الأجل المحدّد (1000 ملي ثانية). للحصول على قيمة المتغيّر i التي مُرِّرت إلى الدالة setTimeout (التي تُنفّذ التعليمات متأخرة بثانية عن وقت حصولها على القيمة) فسنتحتاج إلى دالة أخرى - وليكن اسمها logLater للتأكد من أن الحلقة التكرارية for لا تغيّر قيمة i قبل تنفيذ تعليمات setTimeout: function logLater (i) { setTimeout(function () { console.log(i) }) } for (var i = 1; i < 5; i++) { console.log(i) logLater(i) }; نلاحظ طباعة قيم i الصحيحة: 1، 2، 3 و4. من الجيّد أن الأمور الغريبة التي تحدُث مع المتغيرات المعرَّفة على مستوى الدالة - مثل ما حدث مع حلقة for السابقة - يمكن تفاديها باستخدام let. باستطاعتنا إعادة كتابة المثال الأصلي الذي ينادي setTimeout دون الحاجة لكتابة دالة مستقلة، وذلك عن طريق تعريف المتغيرات بـlet: for (let i = 1; i < 5; i++) { console.log(i) setTimeout(function () { console.log(i) }, 1000) }; ستلاحظ عند تنفيذ الشفرة السابقة أن قيم i تأتي حسب المتوقع. تسهّل المتغيرات المُعرَّفة على مستوى الكتلة - كما رأينا - كتابة الشفرات البرمجية بحذف بعض المشاكل التي تواجهها المتغيرات المعرفة على مستوى الدالة. أنصح - لتسهيل الأمور - باستخدام let بدلا من var عند تعريف المتغيّرات في جافاسكريبت. ننتقل بعد أن تعرّفنا على عمل let إلى const والفرق بين الاثنتين. الفرق بين let وconst تتشابه let وconst في أنهما تعرّفان المتغيرات على مستوى الكتلة. يكمن الفرق في أن المتغيرات التي تُعرَّف بـconst لا يمكن تغيير قيمتها بعد تعريفها أول مرة. const name = 'Zell' name = 'Sleepy head' // TypeError: Assignment to constant variable. let name1 = 'Zell' name1 = 'Sleepy head' console.log(name1) // 'Sleepy head' بما أن قيم المتغيرات المعرفة بـconst لا يمكن التعديل عليها فهي مناسبة للمتغيرات ذات القيمة الثابتة. فلنفترض أن لدينا زرا لفتح نافذة منبثقة. أعرف أنه لن يكون هناك سوى زرّ واحد من هذا النوع ولن يُعدَّل عليه. استخدم const في هذه الحالة. const modalLauncher = document.querySelector('.jsModalLauncher') أفضّل دائمًا استخدام const عند تعريف المتغيّرات كل ما كان ذلك ممكنًا، لأني أتأكد من أن قيمة المتغيّر لن يُعدَّل عليها؛ في ما عدا ذلك وفي جميع الحالات المتبقية أستخدم let. الدوال السهمية يُشار إلى الدوال السهمية بالعلامة <=، وهي اختصار لإنشاء دوال مجهولة الاسم Anonymous functions. يمكن استخدام هذه الدوال في أي مكان يُمكن استخدام الكلمة المفتاحية function فيه. على سبيل المثال: let array = [1,7,98,5,4,2] // استخدام دالة مجهولة الاسم حسب الطريقة القديمة (الإصدار ES5) var moreThan20 = array.filter(function (num) { return num > 20 }) // استخدام الدوال السهمية let moreThan20 = array.filter(num => num > 20) تقلّل الدوال السهمية من حجم الشفرة البرمجية وبالتالي تكون هناك أماكن أقل للأخطاء؛ كما تسهّل فهمَ الشفرة البرمجية عند التعود على أسلوبها. فلنر التفاصيل العملية للدوال السهمية. إنشاء الدوال السهمية ربما تكون متعوّدا على إنشاء الدوال في جافاسكريبت على النحو التالي: function namedFunction() { // Do something } ولاستخدامها: namedFunction() توجد طريقة أخرى لإنشاء الدوال وهي إنشاء دالة مجهولة الاسم وإسنادها إلى متغيّر. لإنشاء دالة مجهولة الاسم فإننا نحذف الاسم من تعريف الدالة: var namedFunction = function() { // Do something } توجد طريقة ثالثة فإنشاء الدوال، وهي إنشاءها مباشرة في معامل دالة أخرى؛ وهذه هي الطريقة الأكثر انتشارًا لإنشاء الدوال مجهولة الاسم. في ما يلي مثال: // استخدام دالة مجهولة الاسم في معامل راجع Callback button.addEventListener('click', function() { // Do something }) بما أن الدوال السهمية هي اختصارات للدوال مجهولة الاسم فإنه يمكن إحلالها في أي مكان توجد به دوال مجهولة الاسم. أمثلة: // دالة عادية const namedFunction = function (arg1, arg2) { /* do your stuff */} // دالة سهمية const namedFunction2 = (arg1, arg2) => {/* do your stuff */} // دالة عادية في معامل راجع button.addEventListener('click', function () { // Do something }) // دالة سهمية في معامل راجع button.addEventListener('click', () => { // Do something }) هل لاحظت التشابه؟ في الأساس حذفنا الكلمة المفتاحية function وأبدلناها بالعلامة <= مع تغيير موضعها قليلا. هل تقتصر الدوال السهمية على إحلال <= مكان function؟ أم أن هناك تفاصيل أخرى؟ صيغة كتابة الدوال السهمية في الواقع، تختلف كتابة الدوال السهمية حسب عامليْن هما: عدد المعاملات المطلوبة الحاجة للإرجاع الضمني Implicit return (لنتيجة التنفيذ) العامل الأول هو عدد المعاملات المُممرَّرة إلى الدالة السهمية. يمكنك حذف الأقواس التي تحيط بالمعاملات إن كان لديك معامل واحد, إن لم توجد معاملات فيمكنك إبدال الأقواس () بعلامة تسطير سفلي _. الصيغ التالية كلّها صحيحة لكتابة دالة سهمية: const zeroArgs = () => {/* do something */} const zeroWithUnderscore = _ => {/* do something */} const oneArg = arg1 => {/* do something */} const oneArgWithParenthesis = (arg1) => {/* do something */} const manyArgs = (arg1, arg2) => {/* do something */} العامل الثاني في صيغة كتابة الدوال السهمية هو الحاجة لإرجاع النتيجة ضمنيا. تضيف الدوال السهمية مبدئيًا كلمة return المفتاحية إن كانت شفرة الدالة تمتدّ على سطر واحد فقط ولم تكن مضمّنة في كتلة (بين قوسين معكوفين {...}). ‘الطريقتان التاليتان في كتابة الدوال السهمية متكافئتان: const sum1 = (num1, num2) => num1 + num2 const sum2 = (num1, num2) => { return num1 + num2 } العاملان المذكوران أعلاه هما السبب في كونك تستطيع كتابة المتغيّر moreThan20 بالطريقة المختصرة التي رأيناها سابقًا: let array = [1,7,98,5,4,2] // بدون استخدام ميزات ES6 var moreThan20 = array.filter(function (num) { return num > 20 }) // باستخدام ميزات ES6 let moreThan20 = array.filter(num => num > 20) بالمختصر، الدوال السهمية رائعة. ستحتاج لبعض الوقت حتى تتعوّد عليها. حاول استخدامها ومع الزمن ستعتادها. أريد قبل إنهاء الحديث عن الدوال السهمية تعريفك بتفصيل عمليّ آخر يسبّب الكثير من الخلط عند استخدام هذه الدوال. المتغيّر this تختلف قيمة المتغيّر this المُعرَّف مسبقا حسب طريقة استدعائه. تكون قيمة المتغيّر this الكائن Window عند استدعاء المتصفّح له خارج أي دالة. console.log(this) // Window عند استدعاء المتغيّر داخل دالة بسيطة فإن قيمته ستكون الكائن العام Global object (أي الكائن Window عندما يتعلّق الأمر بالمتصفّح). function hello () { console.log(this) } hello() // Window تسند جافاسكريبت دائما الكائن Window إلى المتغيّر this عندما يُستدعى من دالة بسيطة (مثل setTimeout). عند استخدام المتغيّر داخل تابع Method فإن القيمة تكون كائن التابع: let o = { sayThis: function() { console.log(this) } } o.sayThis() // o يحيل المتغيّر this إلى الكائن المُنشَأ حديثا عند استدعائه داخل دالة مشيّدة Constructor: function Person (age) { this.age = age } let greg = new Person(22) let thomas = new Person(24) console.log(greg) // this.age = 22 console.log(thomas) // this.age = 24 أما عند استخدام المتغيّر this داخل مستمع لحدث Event listener فإن قيمته تكون العنصُر الذي أطلق الحدث: let button = document.querySelector('button') button.addEventListener('click', function() { console.log(this) // button }) يظهر من الأمثلة السابقة أن قيمة this تحدّدها الدالة التي تستدعيه. تعرّف كل دالة قيمة خاصة بها لـthis. لا تُربَط this في الدوال السهمية بقيمة جديدة أبدا، مهما كانت طريقة استدعاء الدالة. تبقى قيمة المتغيّر this مساوية دائما لقيمة this في السياق الذي توجد به الدالة السهمية. يبدو الأمر مربكًا نوعًا ما، لذا سنأخذ بضعة أمثلة للشرح. أولا؛ لا تستخدم أبدا دوال سهمية لتعريف توابع الكائنات؛ لأنك لن تستطيع حينها الإحالة إلى الكائن باستخدام المتغيّر this: let o = { // تجنّب تعريف التوابع بدوال سهمية notThis: () => { console.log(this) // Window this.objectThis() // Uncaught TypeError: this.objectThis is not a function }, // استخدم دوال عادية لتعريف التوابع objectThis: function () { console.log(this) // o }, // يمكن أيضا استخدام الاختصار التالي لتعريف التوابع objectThis2 () { console.log(this) // o } } ثانيًّا؛ من المستحسَن ألا تستخدم الدوال السهمية لإنشاء مستمعات لأحداث لأن this لن تحيل إلى العنصُر الذي ربطت به المستمع. إن فعلت فيمكنك الحصول على السياق الحقيقي لـthis باستخدام event.currentTarget: button.addEventListener('click', function () { console.log(this) // button }) button.addEventListener('click', e => { console.log(this) // Window console.log(event.currentTarget) // button }) ثالثًا؛ قد تحتاج لاستخدام this مع الدوال السهمية في أماكن تتبدّل فيها قيمة المتغيّر بدون رغبتك. الدالة setTimeout مثال على ذلك. بهذه الطريقة لن تحتاج للتعامل مع مشاكل this، that وself الاعتيادية: let o = { // Old way oldDoSthAfterThree: function () { let that = this setTimeout(function () { console.log(this) // Window console.log(that) // o }) }, // Arrow function way doSthAfterThree: function () { setTimeout(() => { console.log(this) // o }, 3000) } } الاستخدام السابق مفيد جدًا عندما تحتاج لحذف صنف Class أو إضافته بعد انقضاء مدة معينة: let o = { button: document.querySelector('button') endAnimation: function () { this.button.classList.add('is-closing') setTimeout(() => { this.button.classList.remove('is-closing') this.button.classList.remove('is-open') }, 3000) } } في الختام، استخدم الدوال السهمية في أي مكان آخر لتجعل شفرتك البرمجية أنظف كما في مثالنا السابق moreThan20: let array = [1,7,98,5,4,2] let moreThan20 = array.filter(num => num > 20) سنتعرّف في مقال لاحق على ميزات أخرى جديدة في الإصدار ES6. ترجمة - بتصرّف - للمقال Introduction to commonly used ES6 features لصاحبه Zell.
  5. نكتُب شفرات برمجيةً أساسا لحلّ مشاكل. مالذي يحدُث عندما تنقر على زرّ؟ هذه أيضًا مشكلة وينبغي علينا - نحن المطورين - حلّها. نبدأ هذا الدّرس بحلّ مشكلة صغيرة. عدّ التفاحات إن كانت لديك 4 تفاحات واشتريت 27 تفاحة أخرى فكم سيكون لديك من تفاحة؟ اكتُب الإجابة في محرّر النصوص. ما هي إجابتك؟ // هل هي هذه؟ 31 // Or أم هذه؟ 4 + 27 الإجابتان صحيحتان، إلا أن الأخيرة أحسن؛ إذ أنك تترك لجافاسكريبت عبْء الحساب وتخبره كيف يصل إلى النتيجة. ولكن لا يزال عندنا مشكلة في الشفرة السابقة. إنْ نظرت إلى 4 + 27 خارج سياق مشكل التفاحات، فهل ستعرف أننا نعدّ التفاحات التي تحملها الآن؟ الأرجح أن الإجابة هي لا. الأفضل هو استخدام الطريقة الرياضية لإحلال متغيّرات مكان الأعداد 4 و27؛ إن فعلنا ذلك فستكون لدينا القدرة على كتابة شفرة برمجية ذات معنى: initialApples + applesBought initialApples: عدد التفاحات الابتدائي. applesBought: عدد التفاحات المشتراة. تُسمّى عمليّة إحلال متغيّر باسم initialApples مكان العدد 4 بتعريف المتغيّر Declaring a variable. تعريف المتغيّرات تُعرَّف المتغيّرات بالصيغة التالية: const variableName = 'value' توجد أربعة أجزاء في الجملة السابقة يجب الانتباه إليها: اسم المتغيّر variableName القيمة Value علامة الإسناد Assignment = الكلمة المفتاحية const اسم المتغيّر تُشير variableName إلى اسم المتغيّر الذي أنت بصدد تعريفه. يمكنك إعطاء المتغيّر أي اسم تريده بشرط: أن يكون كلمة واحدة أن يتكوّن فقط من حروف لاتينية (a-z, A-Z)، أرقام (0-9) أو علامة تسطير سفلي _ ألّا يبدأ برقم ألّا يكون كلمة محجوزة Reserved keywords في جافاسكريبت إن أردت استخدام أكثر من كلمة في اسم متغيّر فستحتاج لإدماج الكلمات معا وكتابة الحرف الأول من كل الكلمات الموجودة بعد الكلمة الأولى بحرف كبير Capital letter، تُسمّى هذه الطريقة بـ Camel case. المتغيّر applesToBuy مثال على كتابة متغيّر باسم مكوّن من كلمات عدّة. القيمة القيمة هي ما تريد أن يكونه المتغيّر. يمكن للقيمة أن تكون بيانات أوليّة Primitives (مثل سلاسل المحارف Strings والأعداد) أو كائنات (مصفوفات ودوالّ). علامة الإسناد = في جافاسكريبت لا تعمل علامة الإسناد = بنفس طريقة عمل التساوي = في الرياضيات. لذا يتوجّب عدم الخلط بينهما. عندما تستخدم العلامة = في جافاسكريبت فأنت تُسنِد قيمة جزء العبارة الموجود يمين العلامة = تُسنده إلى الجزء الموجود يسار العلامة. في المثال أدناه نُسنِد القيمة 4 إلى المتغيّر initialApples. const initialApples = 4 أو بعبارة أخرى نعطي المتغيّر initialApples القيمة 4. إن طلبت طباعة المتغيّر initialApples فستجد أن النتيجة تساوي 4. التقويم قبل الإسناد لا يُخزّن المتغيّر سوى قيمة وحيدة؛ فإذا كانت لديك معادلة على يمين العلامة = فإن مفسّر جافاسكريبت سيُنفّذ المعادلة الموجودة على الطرف الأيمن ثم بعد ذلك يُسنِد القيمة المُتحصَّل عليها إلى المتغيّر. const initialApples = 4 const applesToBuy = 27 const totalApples = initialApples + applesToBuy سيبدأ جافاسكريبت عند تعريف المتغيّر totalApples في المثال أعلاه بتقويم العبارة initialApples + applesToBuy (التي تعطي النتيجة 31) ثم بعد ذلك يُسنِد القيمة 31 إلى المتغيّر totalApples. الكلمة المفتاحية const توجد ثلاث كلمات مفتاحية لتعريف المتغيّرات، const إحداها. الكلمتان الأخريان هما let وvar. تُستخدَم كل من الكلمات الثلاث لتعريف متغيّرات؛ إلا أنه يوجد اختلاف بين عملها. الفرق بين const وlet وvar أُتيح استخدام كلّ من const وlet في الإصدار السادس من جافاسكريبت ES6، ولهما خصوصيّات مقارنة مع var المتاحة منذ إصدارات سابقة، والتي أصبح استخدامها غير منصوح به. يؤدّي تعريف متغيّر بالكلمة المفتاحية const إلى انعدام إمكانيّة إسناد قيمة جديدة للمتغيّر بعد تعريفه. يعني هذا أن الشفرة التالية ستُنتِج خطأ عند تنفيذها: const applesToBuy = 22 // إعادة إسناد قيمة لمتغيّر عُرِّف بـ const يؤدي إلى خطأ أثناء التنفيذ applesToBuy = 27 أما إن عرّفت متغيّرا بالكلمة المفتاحية let فسيمكنك إسناد قيمة جديدة له دون خطأ: let applesToBuy = 22 applesToBuy = 27 console.log(applesToBuy) أيهما يجب أن أستخدم const أم let؟ في البداية سيكون استخدامُ let بدلا من const أسهل وأقل إثارة للأخطاء؛ إلا أنك مع الوقت وبعد كتابة برامج عدّة ستلاحظ أنه من الأحسن لك التقليل من إمكانية إسناد قيم جديدة للمتغيّرات باستخدام const. ليس هذا الدرسُ التقديمي مناسبا للدخول في تفاصيل أسباب استخدام const لتعريف المتغيّرات. لكن بما أنك ستبدأ في استخدام const أكثر من let عند اكتساب الخبرة بكتابة برامج عدّة بجافاسكريبت فمن الأنسب التعوّد من الآن على هذا الأمر. بالنسبة لـvar فليست لك حاجة في استخدامها، const و let أفضل بكثير. الخلاصة تُستخدَم المتغيّرات في جافاسكريبت للاحتفاظ بقيم. يمكن للمتغيّرات تخزين أي نوع من القيم، سواء كانت بيانات أوليّة أو كائنات. تختلف العلامة = في جافاسكريبت عن علامة التساوي = في الرياضيّات، وتدلّ على الإسناد. ابتعد عن الكلمات المحجوزة لتسمية المتغيّرات واكتب أسماء المتغيّرات المكوّنة من عدّة كلمات وفق أسلوب Camel case. توجد ثلاث كلمات مفتاحية لتعريف المتغيّرات في جافاسكريبت وهي const وlet وvar. استخدم let عندما تريد أن تتاح لك إمكانية التعديل على قيمة المتغيّر. لم تعد توجد حاجة لاستخدام الكلمة المفتاحية var في جافاسكريبت. ترجمة - بتصرّف - للمقال What are variables and why use them in JavaScript لصاحبه Zell Liew حقوق الصورة البارزة محفوظة لـ Freepik
  6. تعرّفنا في مقال سابق على ميزات جديدة في الإصدار ES6 من جافاسكريبت. سنتابع في هذا المقال الحديث عن الميزات الأكثر استخداما من هذا الإصدار وذلك بتناول الإضافات الجديدة التالية: المُعاملان restوspread. تحسينات على الكائنات. القوالب Templates. المعاملان rest وspread يبدو المعاملان rest وspread متشابهين، ويُشار إلى كليهما بثلاث نقاط .... يختلف عمل المعاملين تبعا لطريقة استخدامهما. المعامل rest يعمل rest حرفيا على أخذ بقيّة الشيء ووضعها ضمن مصفوفة. يحوّل المعامل لائحة من المعاملات المحدّدة بفاصلة إلى مصفوفة. فلنر أمثلة عملية على rest. فلنتخيّل أن لدينا دالة باسم add تجمع المعطيات المُمرَّرة لها: sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) // 55 نعتمد في الإصدار ES5 على المتغيّر arguments في كل مرة نحتاج فيها للتعامل مع دالة تأخذ عددا غير محدّد من المعاملات. المتغيّر arguments هو من النوع Symbol الشبيه بالمصفوفات Array. function sum () { console.log(arguments) } sum(1, 2, 3, 4, 5, 6, 7, 8, 9, 10) إحدى الطرق التي يمكن استخدامها لجمع قيم arguments هي تحويلها إلى مصفوفة Array باستخدام Array.prototype.slice.call(arguments) ثم المرور على كل عدد باستخدام تابع مصفوفة مثل forEach وreduce. من السهل استخدام forEach لهذا الغرض، لذا سأشرح استخدام reduce: function sum () { let argsArray = Array.prototype.slice.call(arguments) return argsArray.reduce(function(sum, current) { return sum + current }, 0) } يتيح لنا المعامل rest جعل جميع القيم المفصولة بفاصلة في مصفوفة مباشرة: const sum = (...args) => args.reduce((sum, current) => sum + current, 0) أو إن أردنا التقليل من استخدام الدوال السهمية: function sum (...args) { return args.reduce((sum, current) => sum + current, 0) } عرّجنا سريعا عند الحديث عن تفكيك المصفوفات على المعامل rest بسرعة. حاولنا حينها تفكيك المصفوفة scores إلى القيم الثلاث الأعلى: let scores = ['98', '95', '93', '90', '87', '85'] let [first, second, third] = scores console.log(first) // 98 console.log(second) // 95 console.log(third) // 93 إن رغبنا في الحصول على بقية النتائج فبإمكاننا جعلها في مصفوفة مستقلة بالمعامل rest: let scores = ['98', '95', '93', '90', '87', '85'] let [first, second, third, ...restOfScores] = scores console.log(restOfScores) // [90, 97, 95] تذكّر دائما - لتحنب الخلط - أن المعامل rest يجعل كل شيء في مصفوفة؛ ويظهر في معاملات الدوال وأثناء تفكيك المصفوفات. المعامل spread يعمل المعامل spread بطريقة معاكسة لعمل rest. يأخذ المعامل مصفوفة ويوزّعها على لائحة معاملات يُفصَل بين قيمها بفاصلة: let array = ['one', 'two', 'three'] // نتيجة التعليمتين التاليتين متطابقة console.log(...array) // one two three console.log('one', 'two', 'three') // one two three يُستخدَم المعامل spread غالبا لجمع المصفوفات بطريقة تسهّل قراءتها وفهمها. نريد على سبيل المثال جمع المصفوفات التالية: let array1 = ['one', 'two'] let array2 = ['three', 'four'] let array3 = ['five', 'six'] يُستخدَم التابع Array.concat في الإصدارات القديمة من جافاسكريبت لجمع عدد غير محدَّد من المصفوفات: let combinedArray = array1.concat(array2).concat(array3) console.log(combinedArray) // ['one', 'two', 'three', 'four', 'five', 'six'] يتيح المعامل spread توزيع قيم المصفوفات على مصفوفة جديدة على النحو التالي: let combinedArray = [...array1, ...array2, ...array3] console.log(combinedArray) // ['one', 'two', 'three', 'four', 'five', 'six'] يُستخدَم المعامل spread كذلك لحذف عنصُر من مصفوفة دون التعديل عليها. تُستخدَم هذه الطريقة كثيرا في Redux (يشرح هذا الفيديو) كيف يفعلون ذلك. تحسينات على الكائنات الكائنات من الأمور التي يجدر بكلّ مبرمج جافاسكريبت التعوّد عليها. للتذكير؛ تبدو الكائنات بالهيئة التالية: const anObject = { property1: 'value1', property2: 'value2', property3: 'value3', } يضيف الإصدار ES6 ثلاث ميزات جديدة للكائنات في جافاسكريبت: اختصار قيم الخاصيّات Properties، اختصارات للتوابع Methods، إمكانية استخدام أسماء محسوبة للخاصيّات. سنعرّج على كل واحدة من هذه الميزات. اختصار قيم الخاصيّات هل سبق لك ملاحظة أنك تسند أحيانا متغيّرا إلى خاصية كائن تشترك معه في الاسم؟ شيء من قبيل: const fullName = 'Zell Liew' const Zell = { fullName: fullName } قد ترغب في طريقة أكثر اختصارا من السابق بما أن الخاصيّة fullNameتساوي قيمة المتغيّر fullName. تساعد ميزة اختصار قيم الخاصيّات التي يضيفها الإصدار ES6 في تقليل الشفرة اللازمة لكتابة الكائنات عندما يوافق اسمُ المتغيّر اسمَ الخاصيّة: const fullName = 'Zell Liew' // استخدام ميزة الاختصار في ES6 const Zell = { fullName } // يُترجَم الاختصار في الخلفية إلى ... const Zell = { fullName: fullName } اختصارات التوابع التوابع هي خاصيّات بصيغة دوالّ. تُسمّى هذه الخاصيّات توابع لأنها دوال. في ما يلي مثال على تابع: const anObject = { aMethod: function () { console.log("I'm a method!~~")} } يتيح الإصدار ES6 كتابة التوابع بطريقة مختصرة. يمكننا حذف الكلمة المفتاحية function ولن يتغيّر شيء: const anObject = { // حسب ES6 aShorthandMethod (arg1, arg2) {}, // حسب ES5 aLonghandMethod: function (arg1, arg2) {}, } استخدم هذه الميزة لاختصار توابع الكائنات ولا تلجأ إلى الدوال السهمية لكتابة التوابع (راجع الدوال السهمية في مقال سابق). const dontDoThis = { // تجنّب هذا arrowFunction: () => {} } أسماء محسوبة للخاصيّات تحتاج أحيانا إلى أسماء متغيّرة (ديناميكية) لخاصيّات الكائن. في هذه الحالة ننشئ متغيّرا نضع فيه اسم الخاصيّة الديناميكية. تضطرّ في الإصدارات القديمة من جافاسكريبت لإنشاء الكائن ثم إسناد الخاصيّة على النحو التالي: // متغيّر لحفظ اسم الخاصيّة الجديدة const newPropertyName = 'smile' // ننشئ الكائن أولا const anObject = { aProperty: 'a value' } // ثم نسند قيمة للخاصية الجديدة anObject[newPropertyName] = ':D' // إضافة خاصيّة مختلفة قليلا عن السابقة وإسناد قيمة لها anObject['bigger ' + newPropertyName] = 'XD' // النتيجة // { // aProperty: 'a value', // 'bigger smile': 'XD' // smile: ':D', // } ينزع الإصدار ES6 الحاجة للّف والدوران كما في المثال السابق؛ إذ أصبح بإمكانك إسناد أسماء متغيّرة للخاصيّات مباشرة أثناء إنشاء الكائن بجعل الخاصيّة المتغيّرة داخل أقواس معكوفة: const newPropertyName = 'smile' const anObject = { aProperty: 'a value', // أسماء متغيّرة للكائنات [newPropertyName]: ':D', ['bigger ' + newPropertyName]: 'XD', } // النتيجة // { // aProperty: 'a value', // 'bigger smile': 'XD' // smile: ':D', // } القوالب التعامل مع سلاسل المحارف Strings في جافاسكريبت مزعج للغاية. رأينا مثالا على ذلك في دالة announcePlayer عند الحديث عن المعاملات المبدئية. أنشأنا في تلك الدالة سلاسل محارف فارغة ودمجناها باستخدام عامل الجمع +: function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName) } تأتي القوالب في الإصدار ES6 لتفادي هذا المشكل (كانت القوالب تُسمى سلاسل محارف القوالب Template strings في مسودات ES6). توضع سلاسل المحارف التي نريد جعلها قالبا بين علامتيْ `. يمكن استخدام متغيّرات جافاسكريبت في القوالب داخل ماسك المكان {}$ . هكذا يبدو الأمر: const firstName = 'Zell' const lastName = 'Liew' const teamName = 'unaffiliated' const theString = `${firstName} ${lastName}, ${teamName}` console.log(theString) // Zell Liew, unaffiliated يمكنك كلك إنشاء سلاسل محارف متعدّدة الأسطُر بسهولة. تعمل الشفرة التالية دون مشكل: const multi = `One upon a time, In a land far far away, there lived a witich, who could change night into day` يمكنك كذلك إنشاء شفرات HTML في جافاسكريبت باستخدام القوالب (ربما لا تكون هذه هي أفضل طريقة لإنشاء عناصر HTML، لكنها على كل حال أفضل من إنشاء عناصر HTML الواحد تلو الآخر). const container = document.createElement('div') const aListOfItems = `<ul> <li>Point number one</li> <li>Point number two</li> <li>Point number three</li> <li>Point number four</li> </ul>` container.innerHTML = aListOfItems document.body.append(container) تأتي مع القوالب ميزة الوسوم Tags، وهي دوال يمكن بواسطتها التعامل مع سلاسل المحارف الموجودة في القوالب إن أردت استبدال سلسلة بأخرى. const animal = 'lamb' // هذه الدالة تمثّل وسما const tagFunction = () => { // Do something here } const string = tagFunction `Mary had a little ${animal}` عليّ الاعتراف أنه على الرغم من أن وسوم القوالب تبدو ميزة مفيدة للغاية إلا أنني لم أحتج حتى الساعة لاستخدامها. خاتمة تعرّفنا في هذا الدليل على أكثر ميزات الإصدار ES6 من جافاسكريبت استخداما. سيكون من المفيد التعوّد على استخدام هذه الإضافات كل ما كان ذلك ممكنا، فمن المؤكّد أنها ستجعل شفرتك البرمجية أقصر وأسهل قراءة وبالتالي تزيد من إنتاجيّتك. ترجمة - بتصرّف - للمقال Introduction to commonly used ES6 features لصاحبه Zell.
  7. تعرّفنا في مقال سابق على ميزات جديدة في الإصدار ES6 من جافاسكريبت. سنتابع في هذا المقال الحديث عن الميزات الأكثر استخداما من هذا الإصدار وذلك بتناول الإضافات الجديدة التالية: المعاملات المبدئية التفكيك Destructuring. المعاملات المبدئية تتيح هذه الخاصيّة تحديد معاملات افتراضية عند تعريف الدوال. نأخذ مثالاً لتوضيح الفائدة التي نجنيها من هذا الأمر, سنفترض أننا نريد كتابة دالة تطبع اسم عضو في فريق لعبة. إن كتبنا الدالة حسب الطريقة القديمة - قبل الإصدار ES6 - فستكون شبيهة بالتالي: function announcePlayer (firstName, lastName, teamName) { console.log(firstName + ' ' + lastName + ', ' + teamName) } announcePlayer('Stephen', 'Curry', 'Golden State Warriors') // Stephen Curry, Golden State Warriors يبدو الأمر مناسبا للوهلة الأولى؛ لكن ماذا لو أردنا الإعلان عن اسم لاعب لا ينتمي لأي فريق؟ ستكون نتيجة تنفيذ الدالة أعلاه كالتالي: announcePlayer('Zell', 'Liew') // Zell Liew, undefined طبعا undefined ليس اسم فريق. سيكون من المناسب الإشعار بأن اللاعب غير منتمٍ (Unaffiliated) لأي فريق عند عدم تمرير المعامل للدالة: announcePlayer('Zell', 'Liew', 'unaffiliated') // Zell Liew, unaffiliated يمكننا تحسين الشفرة بالتحقق من تمرير المعامل إلى المتغيّر teamName بدلاً من تمرير القيمة unaffiliated في كلّ مرة: function announcePlayer (firstName, lastName, teamName) { if (!teamName) { teamName = 'unaffiliated' } console.log(firstName + ' ' + lastName + ', ' + teamName) } announcePlayer('Zell', 'Liew') // Zell Liew, unaffiliated announcePlayer('Stephen', 'Curry', 'Golden State Warriors') // Stephen Curry, Golden State Warriors يمكن تقليل الأسطُر باستخدام العوامل Ternary operators المنطقية الثلاثية ?: function announcePlayer (firstName, lastName, teamName) { var team = teamName ? teamName : 'unaffiliated' console.log(firstName + ' ' + lastName + ', ' + team) } يمكن بالاعتماد على ميزة المعاملات المبدئية في ES6 إضافة علامة = أمام اسم المعامل عند تعريف الدالة وسيأخذ المعامل تلقائية القيمة المُحدَّدة عند عدم تمرير قيمة له أثناء استدعاء الدالة. يصبح مثالنا السابق عند كتابته حسب صيغة ES6 كالتالي: const announcePlayer = (firstName, lastName, teamName = 'unaffiliated') => { console.log(firstName + ' ' + lastName + ', ' + teamName) } announcePlayer('Zell', 'Liew') // Zell Liew, unaffiliated announcePlayer('Stephen', 'Curry', 'Golden State Warriors') // Stephen Curry, Golden State Warriors لاحظ أن اسم الفريق يصبح unaffiliated عند عدم تمرير المعامل الأخير إلى الدالة. أمر أخير. يمكنك استخدام القيمة المبدئية للمعامل بتمرير undefined يدويا إلى الدالة. تفيد هذه الطريقة إذا كان المعامل الذي تريد استخدام قيمته المبدئية ليس الأخير في معطيات الدالة: announcePlayer('Zell', 'Liew', undefined) // Zell Liew, unaffiliated التفكيك يعدّ التفكيك طريقة مناسبة لاستخراج قيم من المصفوفات Arrays والكائنات Objects. توجد فروق طفيفة بين تفكيك المصفوفات وتفكيك الكائنات. تفكيك الكائنات فلنفترض أن لدينا الكائن التالي: const Zell = { firstName: 'Zell', lastName: 'Liew' } ستحتاج - للحصول على الاسم الشخصي (firstName) والاسم العائلي (lastName) من Zell إلى إنشاء متغيّريْن وإسناد كل قيمة إل متغيّر: let firstName = Zell.firstName // Zell let lastName = Zell.lastName // Liew يتيح تفكيك الكائن إنشاء هذين المتغيّرين وإسنادهما بسطر واحد: let { firstName, lastName } = Zell console.log(firstName) // Zell console.log(lastName) // Liew مالذي يحدُث هنا؟ تطلُب من جافاسكريبت عند إضافة القوسين المعكوفين على النحو الذي رأيناه أثناء تعريف المتغيّرات تطلُب إنشاء المتغيرات المذكورة وإسناد Zell.firstName إلى firstName وZell.lastName إلى lastName. تترجم جافاسكريبت - الإصدار ES6 - الشفرة التالية: let { firstName, lastName } = Zell إلى: let firstName = Zell.firstName let lastName = Zell.lastName إن سبق استخدام اسم المتغيّر فلن يكون باستطاعتنا تعريفه من جديد؛ خصوصا عند استخدام let أو const. الشفرة التالية غير صحيحة: let name = 'Zell Liew' let course = { name: 'JS Fundamentals for Frontend Developers' // ... other properties } // تتسبّب التعليمة التالية في الخطأ Uncaught SyntaxError: Identifier 'name' has already been declared let { name } = course يمكن تفادي الخطأ في الحالات السابقة بإعادة تسمية المتغيّر أثناء تفكيك الكائن باستخدام النقطتين العموديّتين : على النحو التالي: let { name: courseName } = course console.log(courseName) // JS Fundamentals for Frontend Developers يترجم مفسّر الإصدار ES6 التعليمة عند استخدام النقطتين على النحو التالي: let courseName = course.name أمر أخير بخصوص تفكيك الكائنات. عند استخراج خاصيّة غير موجودة في الكائن فإن المتغيّر يأخذ القيمة undefined: let course = { name: 'JS Fundamentals for Frontend Developers' } let { package } = course console.log(package) // undefined هل تذكر المعاملات المبدئية؟ يمكنك استخدامها لاستخراج المتغيّرات كذلك. الصياغة مطابقة لتلك المستخدمة عند تعريف الدوال: let course = { name: 'JS Fundamentals for Frontend Developers' } let { package = 'full course' } = course console.log(package) // full course يمكنك كذلك إعادة تسمية المتغيّرات مع تحديد قيم مبدئية لها: let course = { name: 'JS Fundamentals for Frontend Developers' } let { package: packageName = 'full course' } = course console.log(packageName) // full course تفكيك المصفوفات يشبه تفكيك المصفوفات تفكيك الكائنات. تُستخدَم الأقواس المُربَّعة [] بدلا من {} لاستخراج متغيّرات من المصفوفة. المتغيّر الأول بين الأقواس يأخذ قيمة العنصُر الأول في المصفوفة والمتغيّر الثاني قيمة العنصر الثاني وهكذا. let [one, two] = [1, 2, 3, 4, 5] console.log(one) // 1 console.log(two) // 2 إن حدّدت متغيرات أكثر من عناصر المصفوفة فإن المتغيرات الزائدة تأخذ القيمة undefined: let [one, two, three] = [1, 2] console.log(one) // 1 console.log(two) // 2 console.log(three) // undefined في الغالب نستخرج العناصر التي نحتاجها من المصفوفة فقط. يمكن استخدام الكلمة المفتاحية rest على النحو التالي لاستقبال بقية المصفوفة: let scores = ['98', '95', '93', '90', '87', '85'] let [first, second, third, ...rest] = scores console.log(first) // 98 console.log(second) // 95 console.log(third) // 93 console.log(rest) // [90, 87, 85] سنخصّص جزءًا من هذا المقال للحديث عن العامل rest، ولكن قبل ذلك سنتحدّث عن ميزة خاصّة عند تفكيك المصفوفات وهي مبادلة المتغيّرات Swapping variables. فلنفترض أن لدينا متغيّريْن a وb: let a = 2 let b = 3 نريد مبادلة هذين المتغيّرين بحيث تكون قيمة a تساوي 3 وقيمة b تساوي 2. نحتاج - في الإصدار ES5 - إلى استخدام متغيّر ظرفي لإكمال المبادلة: let a = 2 let b = 3 let temp // المبادلة temp = a // temp = 2 a = b // a = 3 b = temp // b = 2 فلنر الآن كيفية المبادلة في ES6 بتفكيك المصفوفات: let a = 2 let b = 3; // نحتاج لنقطة فاصلة هنا لأن السطر الموالي يبدأ بقوس معكوف مربَّع // المبادلة باستخدام ميزة تفكيك المصفوفات [a, b] = [b, a] console.log(a) // 3 console.log(b) // 2 تفكيك المصفوفات والكائنات في الدوال أروع ما في التفكيك إمكانيةُ استخدامه في أي مكان تريده. حتى إن بإمكانك تفكيك المصفوفات والكائنات في الدوال. فلنفترض أن لدينا دالة تأخذ مصفوفة من النتائج وتعيد كائنا بالنتائج الثلاث الأعلى. تشبه الدالة التالية ما فعلناه عند تفكيك المصفوفات السابقة: ملحوظة: ليس ضروريا استخدام الدوال السهمية للاستفادة من ميزات ES6 الأخرى. function topThree (scores) { let [first, second, third] = scores return { first: first, second: second, third: third } } توجد طريقة بديلة لكتابة الدالة أعلاه وهي تفكيك المصفوفة أثناء تعريف الدالة. سنقلّل عدد الأسطُر في هذه الحالة كما أننا نعرف أن المعطى المُمرَّر لنا مصفوفة. function topThree ([first, second, third]) { return { first: first, second: second, third: third } } سنرى الآن تفصيلا صغيرا. بما أننا نستطيع الجمع بين المعاملات المبدئية والتفكيك أثناء تعريف الدوال.. فما هي نتيجة الشفرة التالية: function sayMyName ({ firstName = 'Zell', lastName = 'Liew' } = {}) { console.log(firstName + ' ' + lastName) } الأمر معقَّد قليل إذ أننا جمعنا ميزات عدّة في آن. أولا؛ نرى أن الدالة تأخذ معطى واحدا، وهو كائن اختياري تكون قميته {} عند عدم تحديد قيمة. ثانيًّا، نحاول تفكيك الكائن واستخراج المتغيرين firstName وlastName منه واستخدامهما إن وُجدا. أخيرا؛ عندما لا يُعيَّن المتغيران firstName وlastName في الكائن المُمرَّر فإننا نحدّد قيمتيهما بـ Zell وLiew على التوالي. تعطي الدالة النتائج التالية: sayMyName() // Zell Liew sayMyName({firstName: 'Zell'}) // Zell Liew sayMyName({firstName: 'Vincy', lastName: 'Zhang'}) // Vincy Zhang سنتعرّف في مقال لاحق على ميزات أخرى جديدة في الإصدار ES6. ترجمة - بتصرّف - للمقال Introduction to commonly used ES6 features لصاحبه Zell.
×
×
  • أضف...