الوحدة 1 · الخطوات الأولى
النصوص والـ Template Literals
16 دقراءة 4 دبيئة تجريب الكود
الدرس في لمحة
تُنشئ النصوص وتنظّفها، وتقرأ الحروف عبر الفهرس، وتستخدم دوال النصوص اليومية، وتبني مخرجات مقروءة مثل “Lunch: $12.20” باستخدام الـ template literals.
- 1كتابة النصوص
- 2الـ Template literals: قيم داخل النص
- 3الحروف والمواضع والمقاطع
- 4دوال تُرجع نصوصًا جديدة
- 5من النصوص إلى الأرقام وبالعكس
- 6مقارنة النصوص
لا فيديو هنا، بل الشيء الحقيقي: درس مكتوب وأمثلة قابلة للتشغيل واختبار وتدريب.
صارت أرقام Pocket دقيقة، لكن لا أحد يريد أن يقرأ 1220. الناس يريدون Lunch: $12.20. النص في JavaScript اسمه string (سلسلة نصية)، ومعظم ما يراه المستخدم من برنامجك هو نصوص بنيتها أنت.
كتابة النصوص
يمكنك كتابة النص بعلامات تنصيص مفردة أو مزدوجة أو بعلامات backtick:
const a = 'Coffee';
const b = "Sam's lunch";
const c = `Bus`;
console.log(a, b, c);العلامات المفردة والمزدوجة تتصرّفان بالطريقة نفسها؛ اختر أسلوبًا والتزم به (هذه الدورة تستخدم العلامات المزدوجة). واستخدم النوع الآخر حين يحتوي نصّك على علامة تنصيص، كما في "Sam's lunch"، أو “اهرب” منها بشرطة مائلة عكسية: 'Sam\'s lunch'. و\n داخل النص تعني سطرًا جديدًا.
أما علامات backtick فلها شأن خاص، وستستخدمها أكثر من غيرها. إنها تصنع الـ template literals (القوالب النصية).
الـ Template literals: قيم داخل النص
لصق النصوص باستخدام + يصبح فوضويًا بسرعة: "Lunch: quot; + dollars + " (" + category + ")". من السهل أن تنسى مسافة أو علامة تنصيص. أما الـ template literal فيتيح لك كتابة النص مرة واحدة وإسقاط القيم فيه عبر ${ }:
const label = "Lunch";
const cents = 1220;
const category = "food";
const line = `${label}: ${(cents / 100).toFixed(2)} (${category})`;
console.log(line);كل ما داخل ${ } تعبير JavaScript كامل: يُحسب، ثم يُحوَّل إلى نص، ثم يُدرج. هنا تقسم (cents / 100).toFixed(2) لتحصل على 12.2، ثم تحوّلها toFixed(2) إلى النص "12.20" بمنزلتين عشريتين بالضبط. علامة $ الأولى مجرّد علامة دولار عادية؛ فقط $ المتبوعة بـ { هي التي تبدأ الإدراج.
ويمكن للـ template literals أيضًا أن تمتد على عدّة أسطر، وهذا مفيد للرسائل متعدّدة الأسطر:
const report = `Pocket summary
Spent: $22.00
Left: $3.00`;
console.log(report);الحروف والمواضع والمقاطع
النص سلسلة من الحروف، ولكل حرف موضع يُسمّى الفهرس (index)، يبدأ العدّ فيه من 0. وlength تخبرك بعدد الحروف.
const word = "Coffee";
console.log(word.length); // 6
console.log(word[0]); // first character
console.log(word.at(-1)); // last character
console.log(word.slice(0, 3)); // from index 0 up to, not including, 3
console.log(word.slice(3)); // from index 3 to the endword.at(-1) تعدّ من النهاية، وهذا يُغنيك عن كتابة word[word.length - 1].
دوال تُرجع نصوصًا جديدة
تأتي النصوص مع methods (دوال مدمجة) جاهزة، وهي دوال تستدعيها بنقطة. هذه التي ستستخدمها أسبوعيًا:
const raw = " Coffee with Sam ";
const clean = raw.trim();
console.log(clean); // spaces removed from both ends
console.log(clean.toUpperCase());
console.log(clean.includes("Sam")); // true or false
console.log(clean.startsWith("Coffee"));
console.log(clean.replaceAll(" ", "-"));
console.log("7".padStart(3, "0")); // "007"
console.log(`[${raw}]`); // the original is untouchedالسطر الأخير هو الفكرة الأساسية: النصوص غير قابلة للتعديل (immutable). لا توجد method تغيّر نصًا أبدًا؛ كل واحدة تُرجع نصًا جديدًا. فإن أردت الاحتفاظ بالناتج، فخزّنه.
الجمع بين عدّة methods أمر شائع. لتجعل الحرف الأول من تسمية ما حرفًا كبيرًا، خذ الحرف الأول، وحوّله إلى حرف كبير، وأضف إليه الباقي:
const label = "groceries";
const nice = label[0].toUpperCase() + label.slice(1);
console.log(nice);وهناك دالتان أخريان تجيبان عن سؤال “أين هو؟” بدلًا من “هل هو موجود؟”. indexOf("Sam") تُرجع الفهرس الذي يظهر فيه النص لأول مرة، أو -1 إن لم يكن موجودًا أصلًا. وsplit(" ") تقطّع النص إلى أجزاء أينما وجدت الفاصل، وتُعيد إليك قائمة: ["Coffee", "with", "Sam"]. تُسمّى القوائم مصفوفات (arrays)، ولها درس كامل في القسم 3.
من النصوص إلى الأرقام وبالعكس
يعبر Pocket الحدود بين النصوص والأرقام باستمرار. المبالغ أرقام حين تحسب، ونصوص حين تعرضها؛ والمدخلات المكتوبة نصوص إلى أن تحوّلها.
const cents = 450;
console.log(String(cents), typeof String(cents)); // number to string
console.log(`${cents}`.length); // a template literal converts too
console.log(Number("4.50") * 100); // string to number
console.log(Number(" 12 ")); // spaces around digits are ignored
console.log(Number("")); // careful: an empty string becomes 0السطر الأخير فخّ يستحق أن تتذكّره. حقل النص الفارغ يتحوّل إلى 0 لا إلى NaN، فيبدو “المستخدم لم يكتب شيئًا” مطابقًا تمامًا لـ “المستخدم كتب صفرًا”. وحين تتحقّق من النماذج في القسم 4، ستفحص المدخلات الفارغة قبل التحويل.
مقارنة النصوص
=== تقارن النصوص حرفًا حرفًا، وهي حسّاسة لحالة الأحرف: "Food" === "food" تساوي false. والمستخدمون يكتبون الفئات كيفما شاؤوا، لذلك وحّد الشكل قبل أن تقارن: احذف المسافات واختر حالة أحرف واحدة.
const typed = " Food ";
console.log(typed === "food"); // false
console.log(typed.trim().toLowerCase() === "food"); // trueويمكنك أيضًا استخدام < و> مع النصوص. إنهما تقارنان رموز الحروف موضعًا بموضع، وهذا ينجح مع الكلمات البسيطة ذات الأحرف الصغيرة ("apple" < "banana" صحيحة)، ويفشل سريعًا فيما عدا ذلك: "Zebra" < "apple" صحيحة أيضًا، لأن كل حرف كبير له رمز أصغر من كل حرف صغير. يُريك القسم 3 الطريقة الصحيحة لترتيب النصوص، باستخدام localeCompare، التي تتبع قواعد لغة حقيقية.
يستطيع Pocket الآن أن يحمل المبالغ، ويحسب بها بدقة، ويطبعها بشكل يقرؤه الناس. لكن ما لا يستطيعه بعد هو أن يتفاعل: أن ينبّهك حين تتجاوز ميزانيتك، أو أن يعامل الطعام بشكل مختلف عن الإيجار. في القسم التالي يبدأ برنامجك باتخاذ القرارات.
أهم النقاط
- يمكن كتابة النصوص بعلامات تنصيص مفردة أو مزدوجة أو بعلامات backtick؛ وعلامات backtick تصنع الـ template literals، التي تستطيع إدراج القيم عبر
${}وتمتد على عدّة أسطر. - النصوص غير قابلة للتعديل (immutable)، لذلك تُرجع دوال مثل
trim()وtoUpperCase()نصًا جديدًا وتترك الأصلي كما هو. - تُرقَّم الحروف بدءًا من 0، و
lengthتعدّها، وslice(start, end)تنسخ جزءًا حتىendدون أن تشمله. - نسّق السنتات للعرض باستخدام
(cents / 100).toFixed(2)أوIntl.NumberFormat، وأبقِ المبلغ المخزّن رقمًا.