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

لوحة المتصدرين

  1. ZaidEd

    ZaidEd

    الأعضاء


    • نقاط

      2

    • المساهمات

      90


  2. مدون محترف

    مدون محترف

    الأعضاء


    • نقاط

      2

    • المساهمات

      178


  3. عبدالهادي الديوري

    • نقاط

      2

    • المساهمات

      368


  4. E.Nourddine

    E.Nourddine

    الأعضاء


    • نقاط

      1

    • المساهمات

      1458


المحتوى الأكثر حصولًا على سمعة جيدة

المحتوى الأعلى تقييمًا في 05/24/16 في كل الموقع

  1. لترجمة ملفّ مكتوب بلغة Sass إلى ملف CSS يكفي أن تقومي بتنفيذ الأمر التّالي على الطّرفيّة: sass style.scss المُخرج سيكون ملفّ CSS جاهزا، إذا أردت أن يقوم مُترجم Sass بمُشاهدة ملفّ ويقوم بترجمة فوريّة كلّما طرأ تغيير على ملفّ Sass يكفي إضافة --watch كالتّالي: sass --watch style.scss:style.css الأمر سيقوم بترجمة Sass إلى CSS فور استشعار تغيير على الملفّ. بالطّبع يجب أن تكون Sass مُنصّبة على الجهاز، وذلك بتنصيب كلّ من لغة روبي وجوهرة sass. لتنصيب جوهرة sass يُمكن تنفيذ الأمر التّالي: gem install sass قد يحتاج الأمر أعلاه إلى صلاحيّات المدير في أنظمة gnu/linux و Mac OS، لذا يجب إضافة كلمة sudo في بداية الأمر: sudo gem install sass
    2 نقاط
  2. لماذا إعادة تقديم؟ لسوء سُمعة JavaScript حيثُ أنَّها أكثر لُغة برمجة يُساء فهمها في العالم. على الرَّغم من أنَّه في كثيرٍ من الأحيان يتمّ وصفها لُعبة على سبيل السخريّة، إلَّا أنّهُ أسفل بساطتها الخادعة تقعُ بعض ميزات لغةٍ قويّة، أحدُها أنَّها الآن تُستَخدم من قِبَل عددٍ لا يُصدّق من التطبيقاتِ عاليةِ المستوى، ويُبيِّن ذلك أنَّ معرفةً أعمق بهذه التكنولوجيا إنّما هي مهارة مُهمّة لأي مُطوّر لشبكة الإنترنت أو المحمول. من المُفيد أن نبدأ بفكرةٍ عامَّة عن تاريخ هذه اللُّغة. تم إنشاء JavaScript في عام 1995 من قبل Brendan Eich، وهو مهندس في Netscape، وصدرت أولًا مع Netscape 2 في عام 1996. في الأصل كان مُتّفقٌ تسميتها LiveScript، ولكن تمَّ تغيير اسمها في قرارٍ تسويقيٍّ مشؤوم كمُحاولة للاستفادة من شعبية لُغة Java - التابعة لـ Sun Microsystems- على الرغم من أنَّ هُناك عدد قليل جدًا من القواسم المُشتركة بين اللغتين. لقد كان هذا مصدرًا للارتباك منذ ذلك الحين. بعد ثلاثةِ أشهرٍ أطلقت Microsoft نُسخة مُعظمُها مُتوافق مع اللُّغة أسمتها JScript مع IE . قدّمت Netscape اللُّغة إلى Ecma International، وهي مُنظّمةُ معاييرٍ أوروبيّة، وأسفرَ ذلك عن الطبعةِ الأولى من ECMAScript القياسيّة في عام 1997. تلقّت اللُغة عملية تحديث كبيرة كما في ECMAScript Edition 3 في عام 1999، وبَقيتْ مُستقرّة إلى حدٍ كبير منذ ذلك الحين. تمّ التخلي عن الطبعة الرابعة بسبب الخلافات السياسيّة بشأن تعقيد اللُّغة. شكَّلَتْ أجزاءٌ كثيرة من الطبعة الرابعة أساسَ الطبعة ECMAScript 5، التي نُشِرَت في ديسمبر من عام 2009 والطبعة الكبرى 6 والتي سيتمّ نشرها في عام 2015. من أجل الاعتياد، سوف أستخدمُ مُصطلحَ JavaScript طوال الوقت. خلافًا لمُعظم لغاتِ البرمجة، ليس لدى لغة JavaScript مفهوم الإدخال أو الإخراج. إنّما هي مُصمَّمةٌ لتعمل كلغةِ برمجةٍ نصيّة في بيئة استضافة، والأمرُ متروكٌ للبيئة المضيفة لتوفير آليات للتواصل مع العالم الخارجي. بيئةُ الاستضافةِ الأكثرِ شيوعًا هي المُتصفِّح، ولكن بالإمكان أيضًا العثور على مُفسّر JavaScript في Adobe Acrobat, Photoshop, SVG images, Yahoo!'s Widget engine، فضلًا عن البيئاتِ المُتاحةِ من جانب الخادوم مثل node.js. إلا أن قائمة المناطق حيث يتم استخدام JavaScript فقط تبدأ هُنا. تشتملُ اللُّغة أيضًا على قواعد بيانات NoSQL، مثل Apache CouchDB مفتوح المصدر، أجهزة الحاسوب المضمّنة أو بيئات سطح المكتب كاملة، مثل GNOME (واحدة من واجهات المستخدم الرسوميّة الأكثر شعبيّة لأنظمة التشغيل جنو / لينكس). نظرة عامةJavaScript هي لغة ديناميكيّة كائنيّة المنحنى. لديها أنواع types ومُشغِّلين operators، كائنات objects قياسيّة مُدمجة ووظائف methods. يأتي بناءُ الجُملةِ في JavaScript من لُغَتَي Java و C، وتنطبقُ العديدُ من الهياكل في تلك اللغات في JavaScript كذلك. إلَّا أنَّ أحد الفروق الرئيسيَّة هو أنَّه لا توجد فئات Classes في JavaScript. بدلًا من ذلك، يتم إنجاز وظائف الفئة عن طريق نماذج الكائن object prototypes. الفرقُ الرئيسي الآخر هو أن الدوال functions هي كائنات، تُعطى الدوال القدرة على الاحتفاظ بتعليماتٍ برمجيَّة قابلة للتنفيذ وتمريرها مثلها مثل أي كائن آخر. دعونا نبدأ من خلال النَّظر داخل لبنة بناء أي لغة: الأنواع. تقوم برامج JavaScript بمُعالجة القيم، وتنتمي كل تلك القيم إلى نوع. أنواع JavaScript هي: عدد Numberسلسلة Stringمنطقيَّة Booleanدالّة Functionكائن Objectرمز Symbol (جديد في الإصدار 6)كذلك undefined وnull، ويُعتبر هذين النوعين غريبين بعض الشيء. وهُناكَ أيضًا المصفوفة Array، والتي هي نوع خاص من الكائن. والتاريخ Date والمُنشئ RegExp، وهي كائناتٌ تحصلُ عليها مجانًا. ولكي نكون دقيقين من الناحية الفنيّة، الدوال ما هي إلَّا نوعٌ خاصٌّ من الكائن. ولذلك فإن الرسم البياني للنوع يبدو أكثر مثل ما يلي: عدد Numberسلسلة Stringمنطقيَّة Booleanرمز Symbol (جديد في الإصدار 6)كائن Objectدالّة Functionمصفوفة Arrayتاريخ Dateمُنشئ RegExpلا شيء Nullغير مُحدَّد Undefinedكذلك هُناك بعض أنواع الخطأ Error المُدمجة. لكن على كلِّ حال الأمور أسهل كثيرًا إذا اعتمدنا على الرسم البياني الأوَّل. الأرقامالأرقام في JavaScript هي "قِيَم IEEE 754 الدقيقة المُزدوجة في شكل 64-بِت"، وفقًا للمواصفات. لهذا المعنى بعض العواقب المُثيرة للاهتمام. ليس هُناكَ شيءٌ في JavaScript يُشبه العدد الصحيح integer، لذلك عليك أن تكون حذرًا قليلًا مع عمليّاتك الحسابيّة إذا كنتَ معتادًا على الرياضيات في C أو Java. احترس من أشياء مثل: 0.1 + 0.2 == 0.30000000000000004في المُمَارسة العمليّة، يتمّ التعامل مع القيم كما أعداد صحيحة من 32 بِت bit (ويتم تخزينهم بتلك الطريقة في بعض تطبيقات المُتصفِّح)، والتي يمكن أن تكون هامّة للعمليّات التي تستخدم نوع بِت. العوامل الحسابيّة القياسيّة مدعومة، بما في ذلك الجمع والطرح ومُعامل الحساب modulus أو (remainder)، وهكذا دواليك. هناك أيضًا كائن مُدمَج نسيتُ ذِكرَهُ سلفًا يُسمّى Math والذي يُمكنكَ استخدامَهُ إذا كنت ترغب في أداءِ دوالٍّ وثوابت رياضيّة أكثر تقدمًا: Math.sin(3.5); var d = Math.PI * r * r;يُمكنكَ تحويل سلسلة إلى عدد صحيح باستخدام الدالّة المُدمجة ()parseInt. هذه الدالّة تأخذ قاعدة للتحويل كمُعامِل argument ثاني اختياري، والتي ينبغي عليكَ توفيرها دائمًا: parseInt("123", 10); // 123 parseInt("010", 10); // 10رُبَّما تحصُل على نتائج مُذهلة في المُتصفِّحات القديمة (قبل عام 2013) إذا لم توفِّر قاعدة التحويل: parseInt("010"); // 8حَدَثَ ذلك لأن دالّة ()parseInt قرّرت مُعامَلة السلسلة كثُمانيّة octal نظرًا لأن 0 هي الرَّائدة. إذا كُنتَ ترغب في تحويل رقم ثنائيّ binary إلى عدد صحيح integer، فقط يتمّ تغيير القاعدة: parseInt("11", 2); // 3وبالمثل، يمكن تحليل أرقام الفاصِلة العائمة floating point numbers باستخدام الدالّة المُدمجة ()parseFloat والتي تَستَخدِم base 10 دائمًا خلافًا لرفيقتها ()parseInt. يُمكنكَ أيضًا استخدام عامل التشغيل الأحاديّ + لتحويل القيم إلى أرقام: + "42"; // 42يتمّ إرجاع قيمة خاصّة تُسمّى NaN (اختصار لـ”Not a Number”) إذا كانت السلسلة غير رقميّة: parseInt("hello", 10); // NaNNaN سامّة: إذا قُمتَ بتقديمها كمدخل input إلى أي عمليَّة حسابيَّة فإن النتيجة ستكون أيضًا NaN: NaN + 5; // NaNيُمكنكَ اختبار NaN باستخدام الدالّة المُدمجة ()isNaN: isNaN(NaN); // trueلدى JavaScript القيم الخاصّة Infinity و-Infinity: 1 / 0; // Infinity -1 / 0; // -Infinityيُمكنكَ اختبار قيم Infinity و–Infinity وNaN باستخدام الدالّة المُدمجة ()isFinite: isFinite(1/0); // false isFinite(-Infinity); // false isFinite(NaN); // falseمُلاحظة: تقوم دالَّتَي ()parseInt و()parseFloat بتحليل سلسلة حتى تصلا إلى حرفٍ غير صالح لشكل الرَّقم المُحدَّد، بعد ذلك يتمّ إرجاع الرقم الذي تم تحليله إلى تلك النقطة. رغم ذلك فإن المُعامِل "+" يقوم ببساطة بتحويل السلسلة إلى NaN إذا كان هُناك أيّ حرفٍ غير صالح في السلسلة. جرّب محاولة تحليل السلسلة "10.2abc" باستخدام كل طريقة مع نفسك في وحدة التَّحكُّم console، وسوف تفهم الاختلافات بشكلٍ أفضل. السلاسلالسلاسل في JavaScript هي مُتتابعات من الأحرف. ولتعريفٍ أكثر دقة، هي مُتتابعات من أحرف Unicode، يتمّ تمثيل كُل حرف في عدد 16 بِت. لا بُدَّ أنَّ هذا نبأ سار لأي شخص قد تعامل مع نظام التدويل. إذا كُنتَ ترغب في تمثيل حرف واحد، عليكَ استخدام سلسلة من طول 1 فقط. للعثور على طول سلسلة، قٌم باستدعاء خاصيّتها length: "hello".length; // 5هذه أول فُرشاة لدينا مع كائنات JavaScript! هل ذكرتُ لكَ أنَّ بامكانكَ استخدام السلاسل مثل الكائنات أيضًا؟ لديهم وظائف تسمحُ لكَ بمُعالجة السلسلة والوصول إلى معلومات عنها: "hello".charAt(0); // "h" "hello, world".replace("hello", "goodbye"); // "goodbye, world" "hello".toUpperCase(); // "HELLO"أنواع أخرىتُميّز JavaScript ما بين null، وهي القيمة التي تدل على لا شيء (ويمكن الوصول إليها من خلال طريقة واحدة ألا وهي استخدام الكلمة المحجوزة null)، وundefined، وهي قيمة من نوع 'غير معروف' التي تُشير إلى قيمة غير مُهيَّأة - أي قيمة لم يتمّ تعيينها بعد. سوف نتحدَّث عن المُتغيّرات في وقتٍ لاحق، ولكن يُمكن تعريف مُتغيّر في JavaScript دون تحديد قيمة له. إذا قمتَ بذلك، فإنَّ نوع المُتغيّر يُصبِح undefined. في الواقع نوع undefined ثابت. لدى JavaScript نوع Boolean مع القيم الممكنة true وfalse (وكلاهما كلمات محجوزة). يمكن تحويل أيّ قيمة إلى قيمة منطقيّة وفقًا للقواعد التالية: 1- تُصبِح كل من (false، 0، سلسلة فارغة (" ")، NaN، null وundefined) false. 2- تُصبِح كل القيم الأخرى true. يُمكنكَ إجراء هذا التحويل صراحة باستخدام دالَّة ()Boolean: Boolean(""); // false Boolean(234); // trueولكن نادرًا ما يكون هذا ضروريًّا، حيث أن JavaScript ستؤدّي بصمتٍ هذا التحويل عندما تتوقَّع قيمة منطقيَّة، مثل في عبارة if (انظر أدناه). لهذا السبب، ببساطة نذكُر أحيانًا "القيم الحقيقيّة" و"القيم الزائفة" قاصدين القيم التي تُصبح true وfalse على التوالي عند تحويلها إلى القيم المنطقيّة. بدلًا من ذلك يُمكن تسمية هذه القيم "truthy" و"falsy" على التوالي. العمليّات المنطقيّة مثل &&، logical and) || (logical or و! (logical not) مُعتمَدة. انظر أدناه. المُتغيّراتيتمّ تعريف المُتغيّرات الجديدة في JavaScript باستخدام var: var a; var name = "simon";إذا قمتً بتعريف مُتغيّر دون تعيين أيّ قيمة له، فإن نوعه يُصبِح undefined. هناك فارق هام عن لغات أخرى مثل Java ألا وهو أنّ الكُتَل blocks في JavaScript لا تملك نطاق scope؛ فقط الدوال هي التي لها نطاق. لذلك إذا تم تعريف مُتغيّر باستخدام var في جملة مُجمّعة (على سبيل المثال داخل if control structure)، سيكون المُتغيِّر مرئي من قِبَل الدالّة كاملة. إلَّا أنَّه بدءًا من ECMAScript الطبعة 6، تَسمحُ لك تعريفات let وconst امكانيَّة إنشاء مُتغيّرات block-scoped. المُعامِلاتمُعامِلات JavaScript الرقميّة هي +، -، *، / و٪ - وهو عامل ما تبقى. يتمّ تعيين القيم باستخدام = وهناك أيضًا جُمل تعيين مُركبّة مهمّة مثل += و-=. هذه تمتد إلى x = x مُعامِل y. x += 5 x = x + 5يُمكنكَ استخدام ++ و-- للزيادة والإنقاص على التوالي. كذلك بإمكانك أن تَستَخدِم هذه المُعامِلات كمُعامِلات prefix أو postfix. يقومُ المُعامِل + بربط السلسلة: "hello" + " world"; // "hello world"إذا قمتَ بإضافة سلسلة لعدد (أو قيمة أخرى) يتمّ تحويل كل شيء إلى سلسلة أولًا. يُمكن لما يلي أن يوضِّح المقصود: "3" + 4 + 5; // "345" 3 + 4 + "5"; // "75"إضافة سلسلة فارغة إلى شيء هي وسيلة مفيدة لتحويله إلى سلسلة. يُمكن إجراء المُقارنات في JavaScript باستخدام <، >، <= و =>. تَعمَلُ هذه المُقارنات مع السلاسل والأرقام على حدٍّ سواء. تبدو المُساواة أوضح قليلًا عن نظيراتها. تقوم المُساواة المزدوجة == بإجبار تغيير النَّوع إذا قُمتَ باعطائها أنواع مختلفة، وتُعطي نتائج مُثيرة للاهتمام في بعض الأحيان: "dog" == "dog"; // true 1 == true; // trueلتجنُّب إجبار النَّوع، استخدم المساواة الثلاثيَّة: 1 === true; // false true === true; // trueهُناكَ أيضًا != و!==. لدى JavaScript أيضًا مُعامِلات أُحاديّة. إذا كنت ترغب في استخدامها. هياكل التَّحكُّملدى JavaScript مجموعة مُماثِلة لهياكل التَّحكُّم الموجودة في لغات أخرى مثل عائلة C. العبارات الشرطيَّة مدعومة بواسطة if وelse؛ يُمكنكَ سَلسَلَتهم معًا إذا أردت: var name = "kittens"; if (name == "puppies") { name += "!"; } else if (name == "kittens") { name += "!!"; } else { name = "!" + name; } name == "kittens!!"لدى JavaScript حلقات while وحلقات do-while. الأولى جيِّدة لعمليات الحلقات البسيطة؛ والثانية مع تلك الحلقات إذا كنت ترغب في التأكُّد من أن جسد الحلقة يتمّ تنفيذه مرة واحدة على الأقل: while (true) { // an infinite loop! } var input; do { input = get_input(); } while (inputIsNotValid(input))For loop في JavaScript هي نفسها التي في C وJava: فهي تُتيح لكَ توفير معلومات التَّحكُّم للحلقة الخاصّة بك في سطرِ واحد. for (var i = 0; i < 5; i++) { // Will execute 5 times }يَستخدم المُعامِلين && و|| دائرة منطقيَّة قصيرة، وهو ما يعني أنَّها تعتمد على مُعامِلها الأوّل في إذا ما كانت ستُنفِّذ مُعامِلها الثاني. وهذا مُفيد لفحص الكائنات الفارغة قبل محاولة الوصول إلى سماتها: var name = o && o.getName();أو لوضع قيم افتراضيّة: var name = otherName || "default";لدى JavaScript مُعامِل ثُلاثي للتعبيرات الشرطيَّة: var allowed = (age > 18) ? "yes" : "no";يُمكن استخدام جُملة switch مع الفروع المتعدِّدة استنادًا إلى عددٍ أو سلسلة: switch(action) { case 'draw': drawIt(); break; case 'eat': eatIt(); break; default: doNothing(); }إذا لم تقم بإضافة break سوف يتوقّف التنفيذ عن المستوى التالي. وهذا نادرًا جدًا ما تُريد أن يحدث - في واقع الأمر هي تستحقّ وصفها على وجه التحديد fallthrough في تعليق إذا كُنتَ حقَا من المفترض أن تساعد في التصحيح: switch(a) { case 1: // fallthrough case 2: eatIt(); break; default: doNothing(); }يُعتبر شرط default اختياري. يُمكنكَ الحااق تعبيرات في كل من جزء switch وcase إذا أردت ذلك. تُجرَي المُقارنات بين اثنين باستخدام ===: switch(1 + 3) { case 2 + 2: yay(); break; default: neverhappens(); }الكائناتيُمكن اعتبار كائنات JavaScript كمجموعات بسيطة من أزواج name-value. على هذا النحو يمكن تشبيهها بـ: * القواميس Dictionaries في لغة Python * التجزئات Hashes في لغتي Perl وRuby * جداول التجزئة Hash Tables في لغتي C و C++ * HashMaps في لغة Java * مصفوفات الترابط Associative arrays في لغة PHP حقيقة أنّ هياكل البيانات تُستخدم في نطاق واسع ما هو إلَّا دليلٌ على تنوُّعها. وحيثُ أنَّ كل شيء (أنواع الشريط الأساسيَّة bar core types) في JavaScript هو كائن، فإنَّ أيّ برنامج JavaScript يحتوي بطبيعة الحال على قدرٍ كبيرٍ من عمليَّات البحث في جدول التجزئة. وهذا شيءٌ جيِّد والعمليَّات سريعة جدًا! جزء الـ"اسم" هو سلسلة JavaScript، في حين أنَّ القيمة يُمكن أن تكون أي قيمة لـ JavaScript - بما في ذلك المزيد من الكائنات. يَسمحُ هذا لك بامكانيَّة بناء هياكل بيانات من نوع التعقيد التعسُّفي. هُناكَ طريقتان أساسيَّتان لإنشاء كائن فارغ: var obj = new Object();و: var obj = {};و: function Person(name, age) { this.name = name; this.age = age; } // Define an object var You = new Person("You", 24); // We are creating a new person named "You" // (that was the first parameter, and the age..)هذه الطُرق مُتعادِلة لغويًّا؛ يُطلق على الثانية جُملة الكائن الحرفيّة، وهي الأكثر ملاءمة. بناء الجملة هذه هو أيضًا جوهر شكل JSON لذلك ينبغي تفضيل استخدامها في جميع الأوقات. يُمكن الوصول إلى سِمَات الكائن بمُجرّد إنشائه بطريقة من اثنتين: obj.name = "Simon"; var name = obj.name;و: obj["name"] = "Simon"; var name = obj["name"];هاتين الطريقتين مُتعادِلتين لُغويًا أيضًا. للطريقة الثانية ميزة ألا وهي أنَّ اسم الصفة المُميّزة property يتم توفيره كسلسلة، مما يعني أنَّه يُمكن حسابها في وقت التشغيل. رغم ذلك استخدام هذا الأسلوب يمنع بعض تحسينات مُحرِّك ومُصغِّر حجم JavaScript من التطبيق. أيضًا لتحديد set والحصول على get يُمكِنُكَ استخدام الخصائص ذات الأسماء المُتعارَف على أنَّها كلمات محجوزة: obj.for = "Simon"; // Syntax error, because 'for' is a reserved word obj["for"] = "Simon"; // works fineمُلاحظة: ابتداءً من EcmaScript 5، يُمكن استخدام الكلمات المحجوزة كأسماء خاصيّة الكائن المُميّزة object property مُجرّدة، وهذا يُعني أنَّها لا تحتاج إلى أن يتمّ وضعها بين اقتباسات عند تحديد حرفيَّات الكائن. راجع ES5 في Spec. يُمكن استخدام جُملة الكائن الحرفيّة لتهيئة كائن في مُجمَله: var obj = { name: "Carrot", "for": "Max", details: { color: "orange", size: 12 } }يُمكن سَلسَلة الوصول إلى الخاصيّة المُميّزة معًا: obj.details.color; // orange obj["details"]["size"]; // 12المصفوفاتفي الواقع المصفوفات في JavaScript هي نوعٌ خاصٌّ من الكائن. تعملُ المصفوفات كثيرًا مثل الأشياء العاديّة (يُمكن الوصول إلى الخصائص العدديّة باستخدام صياغة [] فقط) ولكن لدى المصفوفات خاصيَّة سحريَّة تُسمَّى ‘length’. هذه الخاصيَّة دائمًا ما تَزِيد بواحد عن أعلى مؤشِّر في المصفوفة. هُناك طريقة واحدة لخلق المصفوفات وهي على النحو التالي: var a = new Array(); a[0] = "dog"; a[1] = "cat"; a[2] = "hen"; a.length; // 3هُناك تأشير أكثر ملاءمة ألا وهو استخدام المصفوفات الحرفيَّة: var a = ["dog", "cat", "hen"]; a.length; // 3لاحظ أن array.length ليس بالضرورة عدد العناصر في المصفوفة. مع مراعاة ما يلي: var a = ["dog", "cat", "hen"]; a[100] = "fox"; a.length; // 101تذكَّر - طول المصفوفة يزيد بواحد عن أعلى مؤشِّر بها. إذا استعلمتَ عن مؤشِّر مصفوفة غير موجود، تحصل على نوع غير مُعرَّف undefined: typeof a[90]; // undefinedإذا أخذتَ ما سبق في الاعتبار، يمكنك التكرار عبر مصفوفة باستخدام ما يلي: for (var i = 0; i < a.length; i++) { // Do something with a[i] }هذه الطريقة غير فعّالة بعض الشيء حيثُ أنّكَ تقوم بالبحث عن الخاصيَّة length مرّة واحدة كل حلقة. تحسينٌ لهذا ما يلي: for (var i = 0, len = a.length; i < len; i++) { // Do something with a[i] }هذا أجمل في المظهر ولكن ذو لغة محدودة: for (var i = 0, item; item = a[i++];) { // Do something with item }نقوم هُنا بإعداد مُتغيّرين. يتم اختبار التعيين أيضًا في الجزء الأوسط من الحلقة للتأكُّد من المصداقيّة - إذا نَجَحَت، ستستمرّ الحلقة في العمل. وحيثُ أن i يتزايد في كل مرّة، سيتمّ تعيين العناصر من المصفوفة إلى عناصر في ترتيب تسلسلي. تتوقّف الحلقة عندما يتمّ العثور على قيم "falsy" (مثل نوع undefined). يجبُ عليكَ استخدام هذه الحيلة فقط مع المصفوفات التي تَعْلَمُ أنَّها لا تحتوي على قِيَم "falsy" (على سبيل المثال مصفوفات من كائنات أو نموذج كائن المُستند DOM). إذا كُنتَ تقوم بالتكرار خلال بيانات رقميَّة يُمكن أن تشمل 0 أو بيانات سلسلة يُمكن أن تشمل سلسلة فارغة يجبُ عليكَ بدلًا من ذلك استخدام تعبير i, len. هُناك طريقة أخرى للتكرار وهي استخدام حلقة for…in. لاحظ أنَّهُ إذا قامَ شخصٌ بإضافة خصائص جديدة لـ Array.prototype فإنَّه سيتم تكرارهم من قِبَل هذه الحلقة أيضًا: for (var i in a) { // Do something with a[i] }إذا كُنتَ ترغب في إلحاق عنصر إلى مصفوفة، ببساطة قُم بذلك كما يلي: a.push(item);تأتي المصفوفات مع عدد من الوظائف. انظر أيضًا وثائق كاملة عن أساليب المصفوفة. الوصفاسم الدالَّةتقوم بإرجاع سلسلة مع toString() من كل عنصر مفصولة بفواصل.a.toString()تقوم بإرجاع سلسلة مع toLocaleString() من كل عنصر مفصولة بفواصل.a.toLocaleString()تقوم بإرجاع مصفوفة جديدة مع عناصر مضافة إليها.a.concat(item1[, item2[, ...[, itemN]]])تقوم بتحويل المصفوفة إلى سلسلة - قيم محدَّدة من قبل العامل المُتغيِّر sepa.join(sep)تقوم بإزلة وإرجاع العنصر الأخير.a.pop()تقوم push بإضافة عنصر واحد أو أكثر في النهاية.a.push(item1, ..., itemN)تقوم بعكس المصفوفة.a.reverse()تقوم بإزالة وإعادة العنصر الأول.a.shift()تقوم بإرجاع مصفوفة فرعيَّة (Sub-array).a.slice(start, end)تقوم بأخذ دالَّة مقارنة اختياريَّة.a.sort([cmpfn])تتيح لك تعديل مصفوفة عن طريق حذف قسم واستبداله بمزيد من العناصر.a.splice(start, delcount[, item1[, ...[, itemN]]])تقوم بإلحاق عناصر إلى بداية المصفوفة.a.unshift([item]) الدوالّالدوالّ هي العنصر الأساسيّ في فهم JavaScript جنبًا إلى جنبٍ مع الكائنات. لا يُمكن للدالّة المُجرّدة أن تكون أسهل من التالية: function add(x, y) { var total = x + y; return total; }تدلُّ التعليمات البرمجيَّة هذه على كل شيء يُمكن معرفته عن الدوال الأساسية. يُمكن لدالّة JavaScript أن تستقبل 0 أو أكثر مما تُدعى مُتغيّرات. يُمكن لجسم الدالّة أن يحتوي على عدد ما تُريد من الجُمل statements، ويُمكن أن تُعرّف مُتغيّراتُها الخاصّة والتي تكون محليّة بالنسبة لتلك الدالّة. يُمكن استخدام جُملة return لإرجاع قيمة في أي وقت ثُمَّ إنهاء الدالّة. إذا لم يتمّ استخدام أيّ جُملة إرجاع (أو تمّ استخدامها وكانت فارغة بدون قيمة) فإن JavaScript تقوم بإرجاع نوع 'غير مُعرَّف'. تُعتبر المُتغيّرات المُسمّاه كمبادئ توجيهيّة أكثر من أي شيء آخر. يُمكنكَ استدعاء دالّة دون تمرير المُتغيّر الذي تتوقّعه الدالّة، في هذه الحالة سيتمّ تعيين المُتغيّر كنوع غير مُعرَّف. add(); // NaN // You can't perform addition on undefinedيُمكنكَ أيضًا تمرير عدد من المُتغيّرات أكثر من العدد الذي تتوقّعه الدالّة: add(2, 3, 4); // 5 // added the first two; 4 was ignoredقد يبدو هذا سخيفًا بعض الشيء ولكن لدى الدوال خاصيَّة الوصول إلى مُتغيّرات إضافيّة داخل أجسامهم تُسمّى arguments، والتي هي كائن مثل المصفوفة تحتوي على كافّة القيم التي تمَّ تمريرُها إلى الدالّة. دعونا نُعيد كتابة دالّة الجمع لتأخذ عدد ما نُريد من القيم: function add() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum; } add(2, 3, 4, 5); // 14رغم ذلك فإنَّ هذا في الحقيقة ليس له أيّ فائدة على مُجرَّد كتابة 2 + 3 + 4 + 5. دعونا نقوم بإنشاء دالّة المتوسِّط: function avg() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; } avg(2, 3, 4, 5); // 3.5هذا مفيدٌ جدًا ولكنَّه يُظهِر مُشكلة جديدة. تأخذ دالّة ()avg قائمة من المُتغيّرات مفصولٌ بينَ كلٍّ منها بفاصِلة - ولكن ماذا لو كُنتَ تُريد أن تجد مُتوسّط مصفوفة؟ يُمكنك كتابة الدالّة على النحو التالي: function avgArray(arr) { var sum = 0; for (var i = 0, j = arr.length; i < j; i++) { sum += arr[i]; } return sum / arr.length; } avgArray([2, 3, 4, 5]); // 3.5سيكونُ من الجميل أن يُصبح بمقدورِنا إعادة استخدام الدالَّة التي قُمنا بإنشائِها مُسبقًا. لحُسن الحظّ، تُمكنُّكَ Javascript من استدعاء دالّة مع مصفوفة من قيم المُتغيّرات العشوائيّة، وذلكَ باستخدام وظيفة apply() من أي كائن دالّة. avg.apply(null, [2, 3, 4, 5]); // 3.5قيمة المُتغيّر الثانية لـ ()apply هي المصفوفة المُستخدمة كقيم المُتغيّرات؛ سيتم نقاش المُتغيّر الأول في وقت لاحق. هذا يؤكد حقيقة أن الدوالّ هي كائنات أيضًا. تُتيح لكَ Javascript إنشاء وظائف مجهولة. var avg = function() { var sum = 0; for (var i = 0, j = arguments.length; i < j; i++) { sum += arguments[i]; } return sum / arguments.length; }هذا هو ما يُعادل لُغويًا نموذج دالّة ()avg. إنَّها قويَّة للغاية حيثُ أنها تُتيحُ لكَ وضع تعريف دالَّة كاملة في أي مكان يُمكنكَ عادة وضع تعبير expression به. يُتيحُ هذا كل أنواع الحِيَل. إليكَ طريقة لـ "اخفاء" بعض المُتغيّرات المحليّة – مثل نطاق الكتلة block scope في لغة C: var a = 1; var b = 2; (function() { var b = 3; a += b; })(); a; // 4 b; // 2تسمحُ لكَ JavaScript استدعاء دوال بشكلٍ متكرِّر. هذا الأمرُ مفيدٌ بشكلِ خاصّ في التعامل مع هياكل الشجرة tree structures، مثل ما تحصُلُ عليه في نموذج كائن المُستند DOM بالمُتصفّح. function countChars(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += countChars(child); } return count; }هذا يُسلّط الضَوْء على مشكلةٍ مُحتملةٍ مع الدوال المجهولة: كيف يُمكن استدعاؤها بشكلِ متكرر إذا لم يكُن لديها اسم؟ تُتيحُ لكَ JavaScript تسمية تعبيرات دالَّة لهذا الغرض. يُمكنكَ استخدام تعبيرات تنفيذ الدالَّة مُباشرةً (IIFEs - Immediately Invoked Function Expressions) المُسمّاة على النحو التالي: var charsInBody = (function counter(elm) { if (elm.nodeType == 3) { // TEXT_NODE return elm.nodeValue.length; } var count = 0; for (var i = 0, child; child = elm.childNodes[i]; i++) { count += counter(child); } return count; })(document.body);الاسم المُقدّم إلى تعبير دالّة على النحو الوارد أعلاه إنَّما هو متاحٌ فقط لنطاقِ الدالّة نفسها. يَسمحُ هذا بمزيدِ من التحسينات تُنفَّذ من قِبَل المُحرِّك وتعليمات برمجيَّة أكثرُ قابليَّة للقراءة على حدٍّ سواء. يظهر الاسم أيضًا في المُصَحِّح debugger وبعض stack trace التي يمكن أن تُوفِّر لكَ الوقت. لاحظ أن دوالّ JavaScript هي نفسها كائنات ويُمكنكَ إضافة أو تغيير خصائص بها تمامًا مثل الكائنات الّتي تطرَّقنا إليها في جُزء الكائنات. الكائنات المُخصَّصَةمُلاحظة: للاطّلاع على نقاش أكثر تفصيلًا عن البرمجة الشيئيَّة في JavaScript، انظر مُقدِّمة إلى JavaScript الشيئيّة. في البرمجة الشيئيّة الكلاسيكيّة، الكائنات هي مجموعات من بيانات ووظائف تعملُ على تلك البيانات. JavaScript هي لغة النموذج القائم والتي لا تحتوي على فئات مثل تِلكَ التي توجد في C++ أو Java. (هذا الامرُ مُربِك أحيانًا للمبرمجين مِمَّن اعتادوا على لغات تحتوي على فئات.) بدلًا من ذلك تَستَخدِم JavaScript الدوال كفئات. لنعتبر أن هُناك كائن عبارة عن شخص Person لديه حقلي الاسم الأول والاسم الأخير. هُناك نوعان من الطرق التي من خلالها قد يتمّ عرض الاسم: كما "الأوَّل الأخير" أو "الأخير، الأوَّل". هذه طريقة لفعل ذلك باستخدام الدوال والكائنات التي ناقشناها سابقًا: function makePerson(first, last) { return { first: first, last: last }; } function personFullName(person) { return person.first + ' ' + person.last; } function personFullNameReversed(person) { return person.last + ', ' + person.first; } s = makePerson("Simon", "Willison"); personFullName(s); // "Simon Willison" personFullNameReversed(s); "Willison, Simon"هذه الطريقة تعمل ولكنَّها سيِّئة جدًا. ينتهي بكَ الأمر مع العشرات من الدوال في مساحتك العامَّة global namespace. ما نحتاجه حقًا هو وسيلة لإرفاق دالَّة بكائن. حيثُ أنَّ الدوال هي كائنات، هذا أمر سهل: function makePerson(first, last) { return { first: first, last: last, fullName: function() { return this.first + ' ' + this.last; }, fullNameReversed: function() { return this.last + ', ' + this.first; } }; } s = makePerson("Simon", "Willison") s.fullName(); // "Simon Willison" s.fullNameReversed(); // "Willison, Simon"هُناك شيء في هذه الجُمل التعليميَّة لم نَرَ من قبل: الكلمة المحجوزة this. تُستَخدَم this داخل الدالَّة وتُشير إلى الكائن الحالي. ما يُعنيه ذلك بالتحديد أنه يتمّ التعيين نِتاجًا عن الطريقة التي قُمتَ باستدعاء الدالَّة بها. إذا قمت باستدعائها باستخدام تأشير النقطة أو تأشير القوس في كائن، يُصبِح هذا الكائن this. إذا لم يتمّ استخدام تأشير النقطة dot notation للاستدعاء، تُشير this إلى الكائن العام global object. لاحظ أن this هي سبب مُتكرِّر للأخطاء. على سبيل المثال: s = makePerson("Simon", "Willison"); var fullName = s.fullName; fullName(); // undefined undefinedعندما نستدعي ()fullName وحدها، من دون استخدام ()s.fullName، فإنَّ هذا مُقيَّد بالنطاق العام global scope. وبما أنَّه لا توجد مُتغيِّرات عامَّة global variables تُسمَّى first أو last فإنَّنا نحصل على نوع undefined لكلِّ واحد منهما. يُمكننا الاستفادة من الكلمة المحجوزة this لتحسين دالَّة makePerson: function Person(first, last) { this.first = first; this.last = last; this.fullName = function() { return this.first + ' ' + this.last; }; this.fullNameReversed = function() { return this.last + ', ' + this.first; }; } var s = new Person("Simon", "Willison");قدَّمنا كلمة محجوزة أُخرى: new. ترتبط new ارتباطًا وثيقًا بـ this. ما تفعله هو أنَّها تخلُق كائن فارغ جديد تمامًا، ثم تدعو الدالَّة المُحدَّدة ويتمّ تعيين this لهذا الكائن الجديد. لاحظ أنَّ الدالَّة المُحدَّدة بواسطة this لا تُرجِع قيمة ولكنَّها فقط تقوم بتعديل كائن this. تُرجِع new كائن this إلى موقع الاستدعاء. يُطلَق على الدوال المُصمَّمة ليتمّ استدعاؤها بواسطة new دوال المُنشِئ. مُمارسة شائعة هي كتابة تلك الدوال بأحرف كبيرة كتذكير لاستدعائهم بواسطة new. لا يزال لدى الدالَّة المُحسَّنة نفس المأزق مع استدعاء ()fullName وحدها. بدأت كائنات Person تُصبِح أفضل ولكن لا تزال هُناك بعض الحوافّ السيِّئة لديها. في كل مرة نقوم بإنشاء كائن Person جديد فنحن نقوم بخلق كائني دالَّة جديدين به كذلك - ألن يكون أفضل لو كانت هذه التعليمات البرمجيَّة مُشتَرَكة؟ function personFullName() { return this.first + ' ' + this.last; } function personFullNameReversed() { return this.last + ', ' + this.first; } function Person(first, last) { this.first = first; this.last = last; this.fullName = personFullName; this.fullNameReversed = personFullNameReversed; }هذا أفضل: نقومُ بخلق دوال الوظيفة مرَّة واحدة فقط، ونُعيِّنُ مراجع لهم داخل المُنشئ. هل بإمكاننا فعل ما هو أفضل من ذلك؟ الجواب هو نعم: function Person(first, last) { this.first = first; this.last = last; } Person.prototype.fullName = function() { return this.first + ' ' + this.last; }; Person.prototype.fullNameReversed = function() { return this.last + ', ' + this.first; };Person.prototype هو كائن مُشتَرَك من قِبَل كافَّة نماذج Person. يُشكِّلُ هذا الكائن جُزءًا من سلسلة بحث (لها اسم خاص وهو "سلسلة النموذج" prototype chain): متى حاولتَ الوصول إلى خاصيَّة غير مُعيَّنة في Person، سوف تتحقَّق JavaScript من Person.prototype لترى ما إذا كانت هذه الخاصّيّة موجودة هناك بدلًا من ذلك. نتيجة لذلك، أي شيء مخصَّص لـ Person.prototype يُصبِح متاحًا لجميع النماذج من هذا المُنشئ عبر كائن this. هذه أداة قويَّة بشكلٍ لا يُصدَّق حيثُ أنَّ JavaScript تُتيحُ لكَ تعديل نموذج شيء في أيّ وقت في بَرنامجك، ممَّا يُعني أنَّه يُمكنكَ زيادة وظائف إضافيَّة لكائنات موجودة في وقت التَّشغيل: s = new Person("Simon", "Willison"); s.firstNameCaps(); // TypeError on line 1: s.firstNameCaps is not a function Person.prototype.firstNameCaps = function() { return this.first.toUpperCase() }; s.firstNameCaps(); // "SIMON"من المُثير للاهتمام أنَّهُ يُمكنكَ أيضًا إضافة أشياء إلى النموذج الخاصّ بالكائنات المُدمجة في JavaScript. دعونا نُضيف وظيفة إلى سلسلة تقوم بإرجاع هذه السلسلة معكوسة: var s = "Simon"; s.reversed(); // TypeError on line 1: s.reversed is not a function String.prototype.reversed = function() { var r = ""; for (var i = this.length - 1; i >= 0; i--) { r += this[i]; } return r; }; s.reversed(); // nomiSتعمل الطَّريقة الجديدة حتَّى مع حرفيَّات السلسلة string literals "This can now be reversed".reversed(); // desrever eb won nac sihTكما ذكرتُ سالِفًا، يُشكِّل النموذج جزءًا من سلسلة. جذر تلك السلسلة هو Object.prototype والذي من وظائفه ()toString - تلك هي الوظيفة التي يتمّ استدعاؤها عندما تُحاول تمثيل كائن كسلسلة. يُعتبَر هذا مفيدًا من أجل تصحيح كائنات Person: var s = new Person("Simon", "Willison"); s; // [object Object] Person.prototype.toString = function() { return '<Person: ' + this.fullName() + '>'; } s; // "<Person: Simon Willison>"أتذكُرُ كيف احتَوَت ()avg.apply على مُعامِل أوَّل فارغ null؟ يُمكننا إعادة النَّظر في ذلك الآن. المُعامِل الأول في ()apply هو الكائن الذي يجب أن يُعامَل على أنَّهُ 'this'. هذا تنفيذٌ تافه لـ new على سبيل المثال: function trivialNew(constructor, ...args) { var o = {}; // Create an object constructor.apply(o, args); return o; }لا يُعتَبرُ هذا نُسخة طبق الأصل من new لأنها لم تقم بإعداد سلسلة النَّموذج (سيكون من الصَّعب التَّوضيح). هذا ليس شيئًا تستخدمه في كثيرٍ من الأحيان ولكن من المفيد أن تعرف عنه. يُطلَق على مُقتطف ...args (بما في ذلك علامات الحذف) "المُعامِلات المُتبقّية" rest arguments - كما يُوحِي اسمها فهي تحتوي على بقيَّة المُعامِلات. استدعاء var bill = trivialNew(Person, "William", "Orange");يُعادِل تقريبًا var bill = new Person("William", "Orange");لدى ()apply دالَّة أخت اسمها call، والتي أيضًا تُتيحُ لكَ تعيين this ولكنَّها تأخذ قائمة موسَّعة من المُعامِلات بدلًا من مصفوفة. function lastNameCaps() { return this.last.toUpperCase(); } var s = new Person("Simon", "Willison"); lastNameCaps.call(s); // Is the same as: s.lastNameCaps = lastNameCaps; s.lastNameCaps();الدوالّ الداخليّةتعريفات دالَّة JavaScript مسموحٌ بها داخل دوال أخُرى. لقد رأينا هذا من قبل مع دالَّة ()makePerson. هُناك تفصيل مهمّ في الدوال المُتداخلة في JavaScript وهو أنَّه يُمكِنُها الوصول إلى مُتغيِّرات في نِطَاق الدالَّة الأم: function betterExampleNeeded() { var a = 1; function oneMoreThanA() { return a + 1; } return oneMoreThanA(); }يوفِّر هذا قدرًا كبيرًا من الفائدة في كتابة تعليمات برمجيَّة أكثر صيانة. إذا اعتَمَدَتْ دالَّة على واحدة أو اثنتين من الدوال الأُخرى غير المُفيدة لأي جُزء من تعليماتك البرمجيَّة، يُمكنكَ إدخال تلك الدوال ذات المنفعة في الدالَّة التي سيتمّ استدعاؤها من مكان آخر. يُحافظ هذا على عدد من الدوال التي هي في النطاق العام، وهذا دائمًا شيءٌ جيد. يُعتبر هذا عدَّاد كبيرة لإغراء المُتغيِّرات العامَّة global variables. عند كتابة تعليمات برمجيَّة معقَّدة غالبًا ما يكون مُغريًا استخدام مُتغيِّرات عامَّة لتبادُل القيم بين دوالّ مُتعدِّدة - الأمر الذي يؤدِّي إلى تعليمات برمجيِّة من الصعب صيانتها. يُمكنُ للدوالّ المُتداخلة مُشاركة المُتغيِّرات الموجودة في الدالَّة الأم، لذلك يُمكنكَ استخدام هذه الآليَّة لتجميع دالَّتين معًا متى كان هذا منطقيَّا دون تلويث مساحتُكَ العامَّة – ‘محليّات عامَّة’ إذا أردتَ أن تُطلِق عليها ذلك. ينبغي استخدام هذا الأسلوب مع الحذر، إلَّا أنَّ حوذته قُدرة مُفيدة. الإغلاقيقودنا هذا إلى واحدة من التجريدات الأكثر قوّة التي بإمكان Javascript تقديمها - ولكن أيضًا الأكثر تعريضًا للارتباك. ماذا تفعل هذه التعليمات البرمجيَّة؟ function makeAdder(a) { return function(b) { return a + b; }; } var x = makeAdder(5); var y = makeAdder(20); x(6); // ? y(7); // ?يجب أن يكون اسم دالَّة makeAdder قد أوضَح كل شيء: يقوم بخلق دوال 'adder' جديدة، تلك الدوال التي عند استدعائها بواسطة مُعامِل تقوم باضافته إلى المُعامِل الذي تم إنشائهم بواسطته. ما يحدث هُنا هو إلى حدٍّ كبير نفس ما كان يحدث مع الدوال الداخليَّة في وقتٍ سابق: للدالَّة المُعرَّفة داخل دالَّة أخرى حقّ الوصول إلى مُتغيِّرات الدالَّة الخارجيَّة. الفرقُ الوحيدُ هُنا هو أن الدالَّة الخارجيَّة قد عادت، وبالتالي الحس السليم يهدي إلى أن مُتغيِّراتها المحليَّة لم تعد موجودة. لكنها لا تزال موجودة - لولاها دوال adder ما كانت قادرة على العمل. ما هو أكثر من ذلك، هناك نوعان من "نسخ" مختلفة من المُتغيِّرات المحليّة الخاصَّة بـ makeAdder - نُسخة بها a هو 5 ونُسخة بها a هو 20. وبُناءً على ذلك فإن نتيجة استدعاءَات الدالَّة تلك هي على النحو التالي: x(6); // returns 11 y(7); // returns 27إليكَ ما يحدُث فعليًّا. عندما تقوم Javascript بتنفيذ دالَّة يتمّ إنشاء كائن 'نطاق' للاحتفاظ بالمُتغيِّرات المحليَّة التي تم إنشاؤها داخل تلك الدالَّة. يتمّ تهيئتها مع أيّ مُتغيَّر يتمّ ارساله كعامِل دالَّة مُتغيِّر. يُشبه هذا الكائن العام الذي يحتوي على جميع المُتغيِّرات والدوال العامَّة، ولكن هُناك مع بعض الاختلافات الهامَّة: أوَّلُها، يتمَّ إنشاء كائن نطاق جديد تمامًا في كل مرة تبدأ دالَّة بالتنفيذ. ثانيها، لا يُمكن الوصول المُباشِر إلى كائنات النطاق تلك من خلال جُمل Javascript البرمجيَّة الخاصَّة بك، على عكس الكائن العام (الذي يُمكن الوصول إليه كـ this ويُمكن الوصول إليه في المُتصفِّحات كـwindow). على سبيل المثال ليس هُناك آليَّة لتكرار خصائص كائن النِطاق الحالي. لذلك عندما يتم استدعاء makeAdder، يتمّ إنشاء كائن نطاق مع خاصيَّة واحدة: a، والذي هو المُعامِل الذي تمّ تمريره إلى دالَّة makeAdder. تُعيد بعد ذلك makeAdder دالَّة تمّ إنشاؤها حديثًا. في هذه المرحلة عادةً يقوم جامع القُمامة في JavaScript بتنظيف كائن النطاق الذي تمّ خلقه لـ makeAdder، ولكن الدالًّة المُعادة تُحافظ على مرجع إلى كائن النطاق هذا. نتيجة لذلك، لن يكون كائن النطاق القمامة مُجمَّعة إلى أن لا يكون هُناك أيَّة مراجع إلى كائن الدالَّة التي أعادتها makeAdder. تُكوِّن كائنات النطاق سلسلة تُسمَّى سلسلة نطاق scope chain، على غرار سلسلة النَّموذج المُستخدمة من قبل نظام كائن JavaScript. الإغلاق هو مزيجٌ من دالَّة وكائن النِّطاق الذي بِهِ تمّ إنشاء تلك الدالَّة. يُمكِّنُكَ الإغلاق من حفظ الحالة - كما أنَّه كثيرًا ما يمكن استخدامه بدلًا من الكائنات. يُمكِن العثور على عدَّة مُقدِّمات ممتازة للإغلاق هُنا. تسريبات الذَّاكرةأحد الآثار الجانبيّة المؤسفة للإغلاق هو أنَّه يجعل من السَّهل تسرب الذاكرة في Internet Explorer. Javascript هي لغة تجميع البيانات المُهملة - تُخصَّص ذاكرة للكائنات عند إنشائها ويتم استعادة تلك الذَّاكرة من قِبَل المُتصفِّح عندما لا تتبقَّى مراجع إلى كائن. يتم التعامل مع الكائنات التي توفّرها البيئة المضيفة عن طريق تلك البيئة. تحتاج مُستضيفات المُتصفِّح إلى إدارة عدد كبير من الكائنات التي تمثل صفحة HTML المُقدَّمة ألا وهي كائنات الـ DOM. الأمر متروك للمُتصفِّح لإدارة تخصيص واسترداد هذه الكائنات. يستخدم Internet Explorer لهذا آلية جمع القمامة الخاصَّة به، بعيدًا عن الآليَّة المستخدمة لـ JavaScript. إنَّ التفاعل بين الآليَّتين هو ما قد يتسبِّب في تسرُّب الذَّاكرة. يحدث تسرُّب الذاكرة في IE أي وقت يتمّ تشكيل مرجع دائري بين كائن JavaScript وكائن أصلي. تأمَّل ما يلي: function leakMemory() { var el = document.getElementById('el'); var o = { 'el': el }; el.o = o; }تخلُق المراجع الدائريَّة المُشكَّلة بالأعلى تسرُّب للذَّاكرة. لن يقوم IE بتحرير الذَّاكرة المُستخدمة من قِبَل el وo حتَّى يتمّ إعادة تشغيل المُتصفِّح تمامًا. من المُرجَّح ألّا تُلاحَظ الحالة المذكورة أعلاه. يُصبح تسرُّب الذَّاكرة مصدر قلق حقيقي فقط في التطبيقات طويلة التشغيل أو التطبيقات التي تُسرِّب قدرًا كبيرًا من الذَّاكرة بسبب هياكل البيانات الكبيرة أو أنماط التسرُّب داخل الحلقات. نادرًا ما تكون التسريبات واضحة بهذا الشَّكل - في كثيرٍ من الأحيان يمكن أن يكون لهيكل البيانات المسرَّبة عدة طبقات من المراجع تقومُ بالعتيم على مرجع مُعاد. يجعلُ الإغلاق من السَّهل خلق تسرُّب ذاكرة دون قصد. انظر إلى التعليمات البرمجيَّة هذه: function addHandler() { var el = document.getElementById('el'); el.onclick = function() { el.style.backgroundColor = 'red'; }; }تقوم التعليمات البرمجيَّة أعلاه بتحويل العنصر إلى أحمر عند النقر عليه. كما أنَّها أيضًا تخلُق تسرُّب ذاكرة. لماذا؟ لأن الإشارة إلى el قُبِضَت دون قصد في الإغلاق الذي تمَّ إنشاؤه للدالَّة الداخليَّة المجهولة. يخلُق هذا مرجعًا دائريًّا بين كائن JavaScript (الدالَّة) وكائن أصلي (el). هُناك عدد من الحلول لهذه المشكلة. أبسطُها هو عدم استخدام مٌتغيِّر el: function addHandler(){ document.getElementById('el').onclick = function(){ this.style.backgroundColor = 'red'; }; }المُثير للدَّهشة أن هُناك خدعة لكسر المراجعِ الدائريَّة تُقدَّم بواسطة الإغلاق، هذه الخُدعة هي إضافةُ إغلاقٍ آخر: function addHandler() { var clickHandler = function() { this.style.backgroundColor = 'red'; }; (function() { var el = document.getElementById('el'); el.onclick = clickHandler; })(); }يتمُّ تنفيذ الدالّة الداخليّة على الفور وتُخفي محتوياتها عن الإغلاق الذي تمَّ انشاؤه باستخدام clickHandler. خدعة أُخرى جيّدة لتجنب الإغلاق هي كسر المراجعِ الدائريَّة خلال حدث window.onunload. سوف تقوم العديد من مكتبات الحدث بتنفيذِ ذلك بدلًا عنك. لاحظ عمل بذلك يقوم بتعطيل ذاكرة التخزين المؤقت back-forward في فيرفُكس، لذلك يجبُ عليكَ أن لا تُسجِّل مُستمع unload في فَيرفُكس، إلا إذا كان لديك أسباب أخرى للقيام بذلك.
    1 نقطة
  3. يحيى دعنا نتفق على بعض الأساسيات لنكون على توافق في المفاهيم، لغة #C هي كأي لغة أخرى، ولعل أحد المميزات التي تتمز بها هذه اللغة، والتي تأتي ضمن لغات الفيجوال بيسيك من قبل مايكروسوفت، حيث يمكنك بناء تطبيقات سطح مكتب، تطبيقات ويب... بالاعتماد على نفس اللغة والتي هي #C في هذه الحالة، أي أنك ستستخدم نفس الأدوات: textbox، label،Radiobutton...مع بعض الإضافات البسيطة والأدوات الجديدة. كما أن البرمجة على الويب تمتاز ببعض الخصوصية، حيث ستتم برمجة الواجهات بلغة html5 سواء اعتمدت على mode designer أو الكود، بالاضافة إلى Javascript،jQuery،Css والتي تعتبر تكميلا أساسيا في بناء تطبيقات الويب، على أن يكون التعامل مع البيانات، التحكم في الأدوات واستخراج قيمها عن طريق لغة #C، نطلق على البرمجة في الويب بـ #C برمجة ASP.Net بلغة #C. هذه دورة فيديو بـ ASP.Net ِ#C:
    1 نقطة
  4. أي خبرة عملية سابقة يجب أن تضيفها الى السيرة الذاتية الخاصة بك و عادةً ما يتم اختبارك بها من خلال مقابلة العمل أو إختبارات عليك اجتيارها كشرط لقبولك في العمل و يتم من خلالها معرفة مهاراتك و مدى الخبرة والمعرفة التي تمتلكها في هذا المجال . الأفضل لك كتقني أن تحاول المشاركة في المشاريع مفتوحة المصدر و أن تكرس جهدك فيها فقد تلفت نظر بعض الشركات الناشئة أو غيرها.. ولاحقًا يمكنك الاستفادة من حسابك على github في إبراز مهاراتك وخبراتك أمام مقابلات العمل . يمكن أن تتجاهل بعض الشركات خبرتك كمستقل في حال كان مجال عملك لا يحتاجونه في شركتهم، غالبا مدى القبول يتعلق بكيفية عرضك لخبرتك ومهاراتك و حجم ما تعلمته في سنوات عملك كمستقل و مدى حاجة الشركة لخبرتك في هذا المجال كلما ركزت على هذه النقاط كانت فرصتك أفضل.
    1 نقطة
  5. كمايوجد أنواع للصور png ، jpg وغيرها من الأنواع، فإن صيغة png نفسها تتضمن أنواع ومن الفروق بين النوعين ما يلي: png 8 أقل جودة من png 24 وبالتالي سيكون حجمها أقل، ويظهر الفرق جليا عندما تحفظ صورة بشفافية transparency من الفروق المهمة: png 24 تدعم 16 مليون لون بينما png 8 تدعم 256 لونا لكن لا يعني هذا أن png 8 سيئة، يمكنك أن تستفيد منها في تلك الصور التي لا تحتاج أن تجعل خلفيتها شفافة وتلك التي لا تحتوي الكثير من التدرجات اللونية والتي سترفعها على الويب هذا رابط يعطيك مثال عملي للفرق بين النوعين.
    1 نقطة
  6. الفرق بينهما يكمن في الوظيفة خصوصًا، لا تعتقد بالضرورة أن PNG-24 هو النسخة الأعلى جودة والذي صنع لرفع جودة الملف فحسب، فالفرق كما ذكرت يكمن في هدف الاستعمال وأين تستعمل كل واحدةٍ منهما. تبدو جودة صيغة PNG-8 أقل خصوصًا إذا كانت الصورة المرفوعة شفافة الخلفية، حيث ستظهر دقائق صغيرة بيضاء حول الأشكال مقتطعة الخلفية، مما يجعل الصورة أقل دقةً أو وضوحًا بالنسبة للمصممين. يمكنك استخدام هذه الصيغة في لقطات الشاشة التي تريد عرضها على الشابكة. ويمكن الحصول على استفادةٍ كبيرةٍ منها في الصور التي لا تحتوي على خلفيةٍ شفافة ولكنها تحتاج إلى مساحةٍ أقل، فإذا أردت رفع لقطة شاشةٍ أثناء شرحك في مدوّنتك مثلًا، صيغة PNG-8 هي الخيار المثالي لما ستساعدك به من دقةٍ وأخذ مساحةٍ أقل. على الجهة الأخرى، تجد صيغة PNG-24 تأخذ مساحةً مضاعفةً أحيانًا عن صيغة PNG-8، والسبب هو أنها ببساطة أفضل في اقتطاع الأشكال من خلفيّاتها. ستظهر الصورة أعلى جودةً من صيغة PNG-8 لأن هذه الصيغة تقتطع الدقائق البيضاء الصغيرة أكثر من PNG-8 وهي تناسب الملفات مقتطعة الخلفيةِ أكثر.
    1 نقطة
  7. تظهر هذه الرسالة عادةً لعدة أسباب ولها عدة حلول الخطوة 1: إصلاح المُشكلة باستخدام Easy Recovery Essentials يُمكن حل المشكلة من خيار الإصلاح الموجود في Easy Recovery Essentials، وهو متاح حاليًا لنظام التشغيل ويندوز إكس بي وفيستا و7 و8 ويُمكن تحميلها من على أي جهاز كمبيوتر آخر ولكنّ البرنامج مدفوع. 1. تحميل Easy Recovery Essentials، والتأكد من الإشارة على إصدار الويندوز الخاص بك قبل التحميل. وهذا دليل للمساعدة على تحديد ومعرفة إصدار الويندوز الخاص بك (الدليل). 2. حرق البرنامج على إسطوانة DVD خارجية ومن خلال هذا الموقع يوجد شرح لحرق البرنامج على إسطوانة، وهُنا شرح لحرق البرنامج على USB. 3. وضع الإسطوانة أو الفلاشة التي تم حرق البرنامج عليها، ثم إعادة تشغيل جهاز الكمبيوتر. 4. عند تشغيل EasyRE، يجب اختيار الخيار (Automated Repair) والنقر فوق مُتابعة. "صورة توضيحية" 5. بعد ذلك ستظهر نافذة، وبها مُحركات الأقراص الموجودة في جهاز الكمبيوتر، يجب اختيار محرك الأقراص الموجود عليه نسخة الويندوز والضغط على Automated Repair. (صورة توضيحية) 6. سوف يبدأ البرنامج بالبحث عن الخلل وتصحيح الأخطاء تلقائيًا بشكل كامل. 7. عند الانتهاء سوف يظهر تقرير بالنتائج وسوف يُطلب منك عمل إعادة تشغيل للجهاز. 8. عند بدء التشغيل من جديد سوف تُحل المشكلة. الخطوة 2: إصلاح المشكلة بواسطة إسطوانة ويندوز يُمكن حل المشكلة من خلال إسطوانة نسخة الويندوز الخاصة بالجهاز وذلك عبر خيار Repire Your Computer ومن أجل فعل ذلك يجب اتباع الخطوات التالية: 1. وضع قرص نُسخة الويندوز، ثم إعادة تشغيل جهاز الكمبيوتر ثم الضغط على أي زر من أجل الدخول إلى الاسطوانة. 2. عند ظهور نافذة تثبيت الإسطوانة يجب الضغط على NEXT، ثم في أقصى اليسار من الأسفل يجب الضغط على كلمة إصلاح أو Repire Your Computer. (صورة توضيحية) 3. اختيار نظام التشغيل ثم الضغط على NEXT، وبعد الضغط سوف تظهر نافذة بها عدة خيارات نستخدم منها خيار StartUp Repire وهو لإصلاح الويندوز. (صورة توضيحية) 4. الآن يجب الإنتظار حتى تظهر نافذة Restart، وبعد ظهور النافذة يجب الضغط على كلمة Restart. 5. الإنتظار حتى يتم إعادة التشغيل وسوف تُحل المشكلة بإذن الله. الخطوة 3: إصلاح المشكلة بواسطة إسطوانة ويندوز "جزء ثاني" بعد تنفيذ الخطوة السابقة سوف نقوم بإعادة نفس الخطوات ولكن سوف نقوم باختيار خيار آخر، ومن أجل فعل ذلك يجب اتباع الخطوات التالية: 1. وضع قرص نُسخة الويندوز، ثم إعادة تشغيل جهاز الكمبيوتر ثم الضغط على أي زر من أجل الدخول إلى الاسطوانة. 2. عند ظهور نافذة تثبيت الإسطوانة يجب الضغط على NEXT، ثم في أقصى اليسار من الأسفل يجب الضغط على كلمة إصلاح أو Repire Your Computer. 3. اختيار نظام التشغيل ثم الضغط على NEXT، وبعد الضغط سوف تظهر نافذة بها عدة خيارات نستخدم منها خيار Command Prompt. 4. ستظهر نافذة CMD يجب كتابة الأوامر التالية بها بالترتيب: bootrec /RebuildBcd bootrec / fixboot exit يجب الإنتظار حتى يتم الانتهاء من تنفيذ كل أمر. 5. الآن يجب الإنتظار حتى تظهر نافذة Restart، وبعد ظهور النافذة يجب الضغط على كلمة Restart. 6. الإنتظار حتى يتم إعادة التشغيل وسوف تُحل المشكلة بإذن الله. حلول أخرى: حل #1: تحقق ذاكرة الوصول العشوائي (RAM) إذا تم مؤخرًا إضافة ذاكرة RAM جديد لجهاز الكمبيوتر الخاص فيجب المحاولة بفعل الآتي: إزالة وحدات ذاكرة الوصول العشوائي الجديدة التي تمت إضافتها مؤخرًا. ترك 1 فقط من وحدة ذاكرة الوصول العشوائي. إعادة تشغيل الكمبيوتر. حل #2: الهارد ديسك فك الكمبيوتر وتنظيف الهارديسك وفك اسلاكه وإعادة توصيل الأسلاك بالطريقة الصحيحة.
    1 نقطة
  8. بعد استخدامِ أحد أدوات التحديد في برنامج Adobe Photoshop، والمرور على الجزء المراد قصّه، يمكنك استخدام أداة "صقل الحافة" المختصّة بتنعيم حواف التحديد وتحسينه، لفعل ذلك، اضغط بعد إقفال مسار التحديد بزر الفأرة الأيمن واختر من القائمة المنسدلة "تحسين الحافة..."، أو من شريط الأدوات العلوي اضغط "صقل الحافة..." (بالإنجليزية: Refine Edge)، ستظهر نافذة منبثقة تحتوي على عدة خياراتٍ للتحكم بحواف الشكل، يمكنك تعديل نمط الرؤية، تعديل إعدادات التنعيم، والعديد من الخيارات الأخرى، كما يمكنك المرور بالفرشاة ضاغطًا على المناطق التي تود تنعيم تحديدها للتحسين الآلي، خذ وقتك في استكشاف الأدوات لتعرف ما يناسبك منها. أما في حالة أنك قد اقتصصت الشكل وتود تنعيم حوافه، فيمكنك الاعتماد كما ذكر لك الأستاذ زاهر على درس "الدليل الكامل لقص الأشياء في فوتوشوب" من "أكاديمية حسوب" لتجد الأداة الأكثر مناسبةً لحالتك.
    1 نقطة
  9. بداية هل الحاسوب الخاص بك هو من نوع محمول أو مكتبيّ؟ فلحدوث مشاكل من هذا النوع أسباب عديدة والتي أرجّح فيها بالبداية ارتفاع درجة حرارة معالجة فيقوم الجهاز بفصل الكهرباء عنه تلقائيّا حماية له ويمكنك مراقبة حرارة المعالج من خلال برنامج HwMonitor أما الخيار الثاني فهو احتمال وجود عطل في مزوّد الطاقة الخاص بالجهاز أو حدوث عطل كهربائي في أحد دوائر الطاقة الخاصّة باللوحة الأم لذلك أنصحك في البداية من التأكد من حرارة المعالج وفي حال لاحظت ارتفاع درجة حرارته تأكد من عمل مروحة التبريد بشكل جيد بالإضافة إلى تغيير المعجون الحراري الخاص بالمعالج
    1 نقطة
  10. تستخدم كودًا خطرًا في هذا البرنامج! لا أدري لماذا تستخدم gets في حين انّه يمكنك استبدالها بسهولة بـ fgets مع تعديل بسيط على الوسائط الممرّرة لها. هذا بالإضافة إلى استخدامك للدالة close بدلًا من fclose، والقليل من الأخطاء الإملائية. على العموم جرّب البرنامج التالي: #include<stdlib.h> #include<stdio.h> struct etudiants{ int num; char nom[100]; char prenom[100]; char filier[50]; }; struct etudiants etud; /*---------fonction de chercher----*/ int rech(int numrech) { FILE*F; F=fopen("etudiants.txt","r"); do{ fscanf(F,"%d ; %s; %s; %s",&etud.num,etud.nom,etud.prenom,etud.filier); if (etud.num==numrech) { fclose(F); return 1; } } while(!feof(F)); fclose(F); return -1; } /*----ajoute---*/ void ajouteretudiant() { int numrech; FILE*F; F=fopen("etudiants.txt","a"); printf("\n entre le numero du nouveau etudiant:"); scanf("%d",&numrech); fflush(stdin); if (rech(numrech)== -1) { etud.num=numrech; printf("\n entre le nom :"); fgets(etud.nom,255,stdin); fflush(stdin); printf("\n entre le prenom :"); fgets(etud.prenom,255,stdin); fflush(stdin); printf("\n entre la filier :"); fgets(etud.filier,255,stdin); fflush(stdin); fprintf(F,"%d ;%s ;%s %s\n",etud.num,etud.nom,etud.prenom,etud.filier); fflush(stdin); } else { printf("\n cet etudiant exsiste deja"); } fclose(F); } /*---------recherche et affichage------*/ void recherche() { int numR; printf("entrer le numero d'etudiant a rechercher "); scanf("%d",&numR); FILE*F; F=fopen("etudiants.txt","r"); do{ fscanf(F,"%d;%s;%S;%s",&etud.num,etud.nom,etud.prenom,etud.filier); if(numR==etud.num){ printf("-----information dur le stagiaire:-------\n\n"); printf("numero : %d\n",etud.num); printf("nom : %s\n",etud.nom); printf("prenom : %s\n",etud.prenom); printf("filier : %s\n",etud.filier); } } while(!feof(F)); fclose(F); } /*------- suppression---*/ void supprimeretudiant() { char rep; int numrech; printf("entrez le numero d'etudiant a supprimer :"); scanf("%d",&numrech); fflush(stdin); if(rech(numrech)==1) { printf("\n volez vous vraimment supprimer o/n ?"); scanf("%c",&rep); fflush(stdin); if( rep=='o'|| rep=='O') { FILE*Fich,*F; F=fopen("etudiants.txt","r"); Fich=fopen("tempetudiant.txt","a"); do{ fscanf(F,"%d;%s;%s;%S",&etud.num,etud.nom,etud.prenom,etud.filier); if(numrech !=etud.num) { fprintf(Fich,"%d;%s;%s;%s \n\n",etud.num,etud.nom,etud.prenom,etud.filier); }} while(!feof(F)); fclose(F); remove("etudiants.txt"); rename("tempetudiant.txt","etudiants.txt"); printf("suppression effectue eve succees"); } } else{ printf("\n ce numero d'etudiant n'exsite pas"); } } /*--------procedure modifier etudiants-------*/ void modifieretudiant() { FILE*F,*Fich; int num,i; char rep; printf("\n entre le numero de l'etudiant a modifier :"); scanf("%d",&num); fflush(stdin); if(rech(num)==1) { printf("\n voulez vous vraimment modifier o/n ?"); scanf("%c",&rep); fflush(stdin); if(rep=='o'||rep=='O') { F=fopen("etudiants.txt","r"); Fich=fopen("tempetudiant.txt","a"); do{ fscanf(F,"%d;%s;%s;%s",&etud.num,etud.nom,etud.prenom,etud.filier); if(num==etud.num) { etud.num=num; printf("\n entre le nouveau nom :"); fgets(etud.nom, 255, stdin); printf("\n entre le nouveau prenom :"); fgets(etud.prenom,255, stdin); printf("entre le nouvelle filier :"); fgets(etud.filier,255,stdin); printf("\n la modification a reussi"); } fprintf(F,"%d;%s;%s;%s\n\n",etud.num,etud.nom,etud.prenom,etud.filier); } while(!feof(F)); fclose(F); fclose(Fich); remove("etudiants.txt"); rename("tempetudiant.txt" , "etudiants.txt"); } else{ printf("\n le modification a et annule \n"); } } /*else { printf("\n ce numero d'etudiant n'existe pas \n");*/ } /*-------procedure afficher--------*/ void affichertt() { FILE*F; F=fopen("etudiants.txt","r"); printf("la liste des etudiants est :\n\n"); do{ fscanf(F,"%d;%s;%s;%s",&etud.num,etud.nom,etud.prenom,etud.filier); fflush(stdin); printf("%d;%s;%s;%s\n\n",etud.num,etud.nom,etud.prenom,etud.filier); } while(!feof(F)); fclose(F); } /*-------menu principale----*/ int main(){ int choix; char rep; do{ system("cls"); printf("**********MENU*******\n"); printf("1-ajouter un etidiant \n"); printf("2-rechercher unetudiant\n"); printf("3-supprimer un etudiant\n"); printf("4-modifier un etudiant\n"); printf("affiche tous le etudiants\n"); printf("6-quitter\n\n"); do{ printf("\n -etre votre choix :"); scanf("%d",&choix); } while(choix<1 || choix>6); switch(choix) { case 1:ajouteretudiant; break; case 2:recherche(); break; case 3:supprimeretudiant(); break; case 4:modifieretudiant(); break; case 5:affichertt(); break; case 6:break; } printf("\n voulez-vous continuez o/n :"); scanf("%s",&rep); fflush(stdin); } while(rep=='o'||rep=='O');}
    1 نقطة
  11. أهلًا بك صديقي نقلًا عن رد الأستاذ طريف أيضًا الأجوبة هُنا سوف تُفيدك إرسال مقالات إلى أكاديمية حسوب
    1 نقطة
×
×
  • أضف...