
مرحبا ، habrozhiteli! سيسمح لك هذا الكتاب بالتعمق في الموضوع ، وتعلم كيفية كتابة رمز جميل وفعال. سوف تتعلم عن بناء الجملة والسهم والوظائف غير المتزامنة ، والتكرار ، وسلاسل النقوش ، ونطاق الحظر.
مارين هافيربيكي - ممارس. اكتساب الخبرة وتعلم اللغة من خلال العديد من الأمثلة من خلال التدريبات ومشاريع التدريب. أولاً ، ستتعرف على بنية لغة جافا سكريبت ، وإدارة الهياكل والوظائف وهياكل البيانات ، ثم دراسة معالجة الأخطاء وإصلاح الأخطاء ، والوحدات النمطية والبرمجة غير المتزامنة ، ثم الانتقال إلى برمجة المتصفح.
مراجعة هذا الكتاب
ينقسم هذا الكتاب إلى ثلاثة أجزاء كبيرة. يناقش أول 12 فصلاً لغة JavaScript. تتناول الفصول السبعة التالية المتصفحات وكيفية استخدام JavaScript لبرمجتها. أخيرًا ، يخصص فصلان ل Node.js ، وهي بيئة برمجة JavaScript أخرى.
خلال الكتاب ، ستقابل خمسة فصول من المشروعات التي تصف أمثلة أكبر للبرامج حتى تشعر بطعم البرمجة الحقيقية. في ترتيب ظهورها ، سنعمل على إنشاء روبوت للتسليم ولغة برمجة ومنصة ألعاب ومحرر رسومات نقطية وموقع ديناميكي.
يبدأ الجزء اللغوي من الكتاب بأربعة فصول من شأنها تعريفك بالهيكل الأساسي للغة JavaScript. سوف تتعلم عن هياكل التحكم (مثل الكلمة المفتاحية التي رأيتها بالفعل في المقدمة) ، والوظائف (كتابة لبنات البناء الخاصة بك) ، وهياكل البيانات. بعد ذلك ، يمكنك كتابة أبسط البرامج. علاوة على ذلك ، يصف الفصلان 5 و 6 كيفية استخدام الوظائف والكائنات لكتابة المزيد من التعليمات البرمجية المجردة والتحكم في تعقيدها.
بعد الفصل الأول من المشروع الأول ، سيتم متابعة الجزء اللغوي من الكتاب - تكرس الفصول التالية لاكتشاف وتصحيح الأخطاء والتعبيرات العادية (أداة مهمة للعمل مع النص) ، والنمطية (دفاع آخر ضد التعقيد) والبرمجة غير المتزامنة (العمل مع الأحداث التي تدوم لبعض الوقت). الجزء الأول من الكتاب مكتمل بفصل المسودة الثانية.
يصف الجزء الثاني ، الفصول من 13 إلى 19 ، الأدوات التي يستطيع المستعرض الذي يدعم جافا سكريبت الوصول إليها. سوف تتعلم كيفية عرض العناصر على الشاشة (الفصلان 14 و 17) ، والاستجابة لمدخلات المستخدم (الفصل 15) ومشاركتها عبر الشبكة (الفصل 18). يحتوي هذا الجزء أيضًا على فصلين من المشروعات.
بعد ذلك ، يتم وصف Node.js في الفصل 20 ، ويتم إنشاء موقع صغير في الفصل 21 باستخدام الأداة المحددة.
مقتطفات. الجمع مع الحد
هناك شيء آخر شائع يتم في الغالب باستخدام المصفوفات وهو حساب قيمة واحدة بناءً عليها. مثال خاص على هذا هو المثال الذي استخدمناه بالفعل مع مجموعة من الأرقام. مثال آخر هو العثور على الخط الذي يحتوي على معظم الأحرف.
تسمى العملية ذات الترتيب الأعلى التي تنفذ هذا النمط اختصارًا (تسمى أحيانًا الإلتفاف). تقوم هذه العملية بإنشاء القيمة عن طريق الحصول على عنصر واحد من الصفيف بشكل متكرر ودمجها مع القيمة الحالية. عند جمع الأرقام ، نبدأ من الصفر ثم نضيف كل عنصر لاحق إلى المجموع.
معلمات دالة التخفيض ، بالإضافة إلى المصفوفة ، هي وظيفة دمج وقيمة أولية. هذه الوظيفة أكثر تعقيدًا قليلاً من الفلتر والخريطة ، لذلك ألقِ نظرة فاحصة عليها:
function reduce(array, combine, start) { let current = start; for (let element of array) { current = combine(current, element); } return current; } console.log(reduce([1, 2, 3, 4], (a, b) => a + b, 0));
الطريقة القياسية للعمل مع صفائف الحد ، والتي ، بطبيعة الحال ، يتوافق مع هذه الوظيفة ، لديها راحة إضافية. إذا كان الصفيف يحتوي على عنصر واحد على الأقل ، فيمكنك حذف وسيطة البدء. تحدد الطريقة العنصر الأول للصفيف كقيمة أولية وتبدأ في الاختزال من العنصر الثاني.
console.log([1, 2, 3, 4].reduce((a, b) => a + b));
لاستخدام تصغير (مرتين) للعثور على الخط الذي يحتوي على أكثر الأحرف ، يمكننا كتابة شيء مثل هذا:
function characterCount(script) { return script.ranges.reduce((count, [from, to]) => { return count + (to — from); }, 0); } console.log(SCRIPTS.reduce((a, b) => { return characterCount(a) < characterCount(b) ? b : a; }));
تقلل الدالة characterCount النطاقات المعينة لهذا الخط من خلال حساب مجموع أحجامها. لاحظ استخدام التدمير في قائمة المعلمات الخاصة بوظيفة التخفيض. ثم تستخدم المكالمة الثانية للتقليل النتيجة السابقة للعثور على أكبر خط ، ومقارنة الخطين بشكل متكرر وإرجاع الخط الأكبر.
يحتوي الخط هان على أكثر من 89000 حرفًا تم تعيينه له في Unicode القياسي ، مما يجعله أكبر نظام للكتابة في مجموعة البيانات الخاصة بنا. Han خط يستخدم أحيانًا للنصوص الصينية واليابانية والكورية. تحتوي لغاتهم على العديد من الشخصيات الشائعة ، على الرغم من أنها مكتوبة بطريقة مختلفة. قرر Unicode Consortium (الموجود في الولايات المتحدة الأمريكية) النظر في مثل هذه الأحرف كنظام تسجيل واحد من أجل حفظ رموز الأحرف. وهذا ما يسمى هان التوحيد وما زال مزعجا للغاية بالنسبة لبعض الناس.
composability
دعنا نفكر: كيف يمكننا إعادة كتابة المثال السابق (العثور على أكبر خط) دون وظائف الترتيب العالي؟ الكود التالي ليس أسوأ بكثير.
let biggest = null; for (let script of SCRIPTS) { if (biggest == null || characterCount(biggest) < characterCount(script)) { biggest = script; } } console.log(biggest);
ظهرت عدة روابط إضافية ، وأصبح البرنامج أربعة خطوط أطول. ولكن هذا الرمز لا يزال واضحا جدا.
تبدأ وظائف الترتيب العالي في أن تكون مفيدة حقًا عندما تحتاج إلى إنشاء عمليات. على سبيل المثال ، سنكتب رمزًا يحسب متوسط سنة إنشاء خطوط للغات الحية والميتة في مجموعة بيانات.
function average(array) { return array.reduce((a, b) => a + b) / array.length; } console.log(Math.round(average( SCRIPTS.filter(s => s.living).map(s => s.year))));
وبالتالي ، فإن نصوص اللغات الميتة في Unicode أقدم من نصوص اللغات الحية في المتوسط.
هذه ليست إحصاءات مهمة أو مفاجئة بشكل خاص. لكن من المأمول أن توافق على أن الكود المستخدم لحسابه سهل القراءة. يمكن تخيل ذلك على أنه ناقل: نبدأ بتحليل جميع الخطوط وتصفية الأحياء (أو الموتى) ونأخذ سنوات إنشائها ونحسب متوسط القيمة وننهي النتيجة.
يمكن أيضًا تمثيل هذا الحساب كدورة واحدة كبيرة.
let total = 0, count = 0; for (let script of SCRIPTS) { if (script.living) { total += script.year; count += 1; } } console.log(Math.round(total / count));
ولكن في هذا الرمز ، يكون من الصعب فهم ماذا وكيف يتم حسابها. ونظرًا لعدم تقديم النتائج الوسيطة كقيم متسقة ، يجب القيام بالكثير من العمل لفصل شيء مثل المتوسط إلى دالة منفصلة.
فيما يتعلق بما يفعله الكمبيوتر فعليًا ، تختلف هاتان الطريقتان أيضًا اختلافًا جذريًا. الأول ينشئ صفائف جديدة عند تشغيل المرشح والخريطة ، بينما يحسب الثاني فقط بعض الأرقام ، ويقوم بعمل أقل. في العادة ، يمكنك شراء خيار أكثر قابلية للقراءة بسهولة ، ولكن إذا كان عليك معالجة المصفوفات الكبيرة جدًا والقيام بذلك عدة مرات ، فإن نمطًا أقل تجريدًا يمنحك زيادة إضافية في السرعة.
سلاسل ورموز الحروف
استخدام واحد من مجموعات البيانات هو تحديد الخط الذي تتم كتابة جزء معين من النص فيه. لنلقِ نظرة على برنامج يقوم بهذا.
تذكر أنه لكل خط توجد مجموعة من نطاقات رمز الحرف. لذلك ، ومع معرفة رمز الحرف ، يمكننا استخدام الوظيفة التالية للعثور على الخط المقابل (إن وجد):
function characterScript(code) { for (let script of SCRIPTS) { if (script.ranges.some(([from, to]) => { return code >= from && code < to; })) { return script; } } return null; } console.log(characterScript(121));
بعض الطريقة هي وظيفة أخرى ذات ترتيب أعلى. يستغرق اختبار وظيفة وتقارير إذا كان يعود صحيحا لأي عنصر من الصفيف.
ولكن كيف نحصل على رموز الحروف كسلسلة؟
في الفصل الأول ، ذكرت أنه في JavaScript ، يتم تمثيل السلاسل كسلسلة من أرقام 16 بت. هذه هي وحدات رمز ما يسمى. في البداية ، تم افتراض أنه في Unicode ، سيتم وضع رمز الحرف في مثل هذه الكتلة (والتي تعطي أكثر من 65000 حرفًا). عندما أصبح واضحًا أن هذا لم يكن كافيًا ، بدأ كثيرون في الاعتراض على الحاجة إلى استخدام المزيد من الذاكرة لتخزين شخصية واحدة. لحل هذه المشكلة ، تم اختراع تنسيق UTF-16 المستخدم في سلاسل JavaScript. في ذلك ، تشغل الأحرف الأكثر شيوعًا وحدة رمز واحدة 16 بت ، والباقي - وحدتان رمزيتان.
من المقبول عمومًا اليوم أن UTF-16 كانت فكرة سيئة. يبدو أنه تم إنشاؤه لإنتاج أخطاء. يمكنك بسهولة كتابة برنامج تكون فيه وحدات الرموز والحروف متشابهة. وإذا كانت لغتك الأم لا تستخدم أحرفًا تشغل وحدتي كود ، فسوف يعمل هذا البرنامج بشكل جيد. ولكن بمجرد أن يحاول شخص ما استخدام مثل هذا البرنامج للأبجدية الأقل شيوعًا ، على سبيل المثال ، بالنسبة للأحرف الصينية ، فسوف ينهار على الفور. لحسن الحظ ، بعد ظهور الرموز ، تم استخدام وحدتي كود في كل مكان لترميز الشخصيات ، وتم توزيع عبء حل مثل هذه المشكلات بطريقة أكثر إنصافًا.
لسوء الحظ ، فإن العمليات الواضحة باستخدام سلاسل JavaScript ، مثل الحصول على طولها عبر خاصية الطول والوصول إلى محتوياتها باستخدام أقواس مربعة ، لا تتعامل إلا مع وحدات الكود.

لا تقوم طريقة JavaScript charCodeAt بإرجاع رمز الحرف الكامل ، ولكن وحدة الكود. الأسلوب codePointAt الذي يظهر لاحقًا بإرجاع حرف Unicode الكامل. لذلك يمكننا استخدام هذا للحصول على أحرف من سلسلة. لكن الوسيطة التي تم تمريرها إلى codePointAt لا تزال فهرسًا في تسلسل وحدات التعليمات البرمجية. وبالتالي ، من أجل التكرار على جميع الأحرف في السلسلة ، ما زلنا بحاجة إلى حل مسألة ما إذا كانت وحدة أو وحدتان من الكودات تشغل الحرف.
في الفصل السابق ، ذكرت أن for / of loop يمكن أيضًا استخدامها للسلاسل. مثل codePointAt ، ظهر هذا النوع من الحلقة في وقت أدرك فيه المبرمجون بوضوح مشاكل UTF-16. عندما تقوم بتطبيق هذه الحلقة على سلسلة ، فإنها تعطي أحرفًا حقيقية ، وليس وحدات رمز.

إذا كان لديك حرف (وهو عبارة عن سلسلة مكونة من وحدة واحدة أو وحدتين رمزيتين) ، يمكنك الحصول على codePointAt (0) للحصول على الكود الخاص به.
التعرف على النص
لدينا وظيفة characterScript وطريقة لتعداد الحروف بشكل صحيح في حلقة. الخطوة التالية هي حساب عدد الأحرف التي تنتمي إلى كل خط. نحن هنا بحاجة إلى تجريد العد:
function countBy(items, groupName) { let counts = []; for (let item of items) { let name = groupName(item); let known = counts.findIndex(c => c.name == name); if (known == -1) { counts.push({name, count: 1}); } else { counts[known].count++; } } return counts; } console.log(countBy([1, 2, 3, 4, 5], n => n > 2));
تقبل الدالة countBy مجموعة (كل ما يمكن فرزه في / حلقة) ووظيفة تحسب اسم المجموعة لعنصر معين. تقوم دالة countBy بإرجاع مجموعة من الكائنات ، يحتوي كل منها على اسم المجموعة وعدد العناصر التي تم العثور عليها لها.
تستخدم هذه الوظيفة طريقة أخرى للعمل مع المصفوفات - findIndex. تشبه هذه الطريقة إلى حد ما indexOf ، ولكن بدلاً من البحث عن قيمة محددة ، فإنها تعثر على القيمة الأولى التي ترجع الدالة المعطاة إليها بشكل صحيح. إذا لم يتم العثور على العنصر ، فستجد findIndex ، مثل indexOf ، -1.
باستخدام countBy ، يمكننا كتابة دالة تخبر الخطوط التي تم استخدامها في هذا النص.

تقوم الدالة أولاً بحساب الأحرف حسب اسم الخط ، وذلك باستخدام characterScript لمنحهم اسمًا ، وتُرجع السلسلة "بلا" للأحرف التي لا تنتمي إلى أي خط. يقوم عامل تصفية الاتصال بإزالة الإدخال "بلا" من الصفيف الناتج ، حيث أننا لسنا مهتمين بهذه الأحرف.
لتكون قادرًا على حساب النسب المئوية ، نحتاج أولاً إلى الحصول على إجمالي عدد الأحرف التي تنتمي إلى الخط والتي يمكننا حسابها باستخدام طريقة التصغير. إذا لم يتم العثور على مثل هذه الأحرف ، فسوف تُرجع الدالة سلسلة محددة. وإلا ، فإنه يحول نتائج الفرز إلى سلاسل قابلة للقراءة باستخدام الخريطة ، ثم يجمعها باستخدام الصلة.
ملخص
تعد القدرة على تمرير القيم الوظيفية إلى وظائف أخرى جانبًا مفيدًا للغاية في JavaScript. يتيح لك هذا إنشاء وظائف تحاكي العمليات الحسابية باستخدام مسافات. بعد ذلك ، عند استدعاء هذه الوظائف في الكود ، تمتلئ هذه "الفجوات" بقيم وظيفية.
بالنسبة للصفائف ، هناك عدد من طرق الترتيب العالي المفيدة. يمكن استخدام طريقة forEach للتجول بين عناصر الصفيف. تقوم طريقة المرشح بإرجاع صفيف جديد يحتوي فقط على العناصر التي تفي بحالة الشرط الوظيفي. يتم تحويل الصفيف عن طريق تنفيذ وظيفة لكل عنصر باستخدام الخريطة. لدمج كل عناصر الصفيف في قيمة واحدة ، يمكنك استخدام اختزال. تقوم بعض الطرق بالتحقق مما إذا كان أي عنصر يتطابق مع دالة مسند معينة. أخيرًا ، تجد طريقة findIndex موضع العنصر الأول الذي يطابق المسند.
»يمكن الاطلاع على مزيد من المعلومات حول الكتاب على
موقع الناشر»
المحتويات»
مقتطفاتخصم 25 ٪ على كوبون الباعة المتجولين -
جافا سكريبتعند دفع النسخة الورقية من الكتاب ، يتم إرسال كتاب إلكتروني عبر البريد الإلكتروني.