مستوى المقال: مبتدئ — مناسب لأي حد لسه بادئ في البرمجة وعايز يفهم النصوص صح.
لو كتبت "👨👩👧".length في JavaScript وطلعلك 8 بدل 1، ده مش غلط في الكود ولا في المتصفح. ده بالظبط ازاي الكمبيوتر بيشوف النص. في آخر المقال هتعرف تعدّ الحروف صح وتبطّل تتصدم من الأرقام دي.
ليه طول إيموجي واحد بيطلّع 8 في الكود؟
المشكلة باختصار
إنت شايف رمز واحد على الشاشة: عائلة. الكمبيوتر شايف حاجة تانية خالص. .length في JavaScript بيرجّع 8، وlen() في Python بيرجّع 5، وعينك بتشوف 1. تلات أرقام مختلفة لنفس النص. لو بنيت على .length وانت فاكره بيعدّ الحروف اللي المستخدم شايفها، هتقع في باجات حقيقية في حقول الإدخال، وقص النصوص، وعدّ الأحرف.
الأول بمثال: علبة فيها كروت
تخيّل إن عندك علبة، وكل خانة فيها بتاخد كارت صغير واحد بس. عايز تكتب كلمة "باب"، فحطيت 3 كروت: ب، ا، ب. عدّ الكروت = 3، وعدّ الحروف اللي بتشوفها = 3. تمام، كله ماشي.
دلوقتي عايز تحط صورة عائلة. الصورة دي كبيرة، مش بتدخل في خانة واحدة. فبتتقسّم على كذا خانة: خانة للأب، خانة لـ"غرّاية" خفية بتلزق الصورتين، خانة للأم، غرّاية تانية، خانة للبنت. النتيجة: 5 خانات اتملت عشان تطلع لك صورة واحدة. لو عدّيت الخانات هتلاقي 5، رغم إن عينك شايفة صورة واحدة. ده بالظبط اللي بيحصل مع الإيموجي.
الشرح العلمي: 3 طرق مختلفة للعدّ
دلوقتي نرجع للمصطلحات بدقة. النص في الذاكرة بيمر بتلات مستويات، وكل واحد بيعدّ بشكل مختلف:
- Code point (نقطة الترميز): الرقم الرسمي اللي بتديه Unicode لكل رمز. مثلًا الأب
👨= U+1F468. ده "الكارت" المنطقي. - Code unit (وحدة الترميز): ازاي الـ code point ده بيتخزّن فعليًا في الذاكرة. JavaScript بيستخدم ترميز UTF-16، واللي بيخزّن أي رمز كبير زي الإيموجي في وحدتين مش وحدة. ده "الخانة" في العلبة.
- Grapheme (العنقود المرئي): الحرف الواحد زي ما عينك بتشوفه. ده اللي إنت بتقصده لما تقول "حرف".
إيموجي العائلة 👨👩👧 مكوّن من 3 إيموجي (أب، أم، بنت) متلزّقين بفاصل خفي اسمه Zero-Width Joiner (اختصارًا ZWJ، رمزه U+200D). الـ ZWJ ده بيقول للنظام: "اعرض دول كصورة واحدة". النتيجة:
- عدد الـ code points = 5 (أب + ZWJ + أم + ZWJ + بنت). ده اللي Python بيعدّه.
- عدد الـ code units في UTF-16 = 8 (كل إيموجي = وحدتين، وكل ZWJ = وحدة: 2+1+2+1+2). ده اللي JavaScript بيعدّه في
.length. - عدد الـ graphemes = 1. ده اللي عينك بتشوفه.
الكود اللي بيحصل فعلاً
جرّب الكود ده في console المتصفح أو Node 22: