تُخَزَّن النصوص في JavaScript كسلاسل نصية أي سلاسل من المحارف (string of charecter). لا يوجد نوع بيانات مستقل للحرف الواحد (char).
الصيغة الداخلية للنصوص هي دائمًا UTF-16,ولا تكون مرتبطة بتشفير الصفحة.
علامات التنصيص “”
لنراجع أنواع علامات التنصيص (الاقتباس).
يمكن تضمين النصوص إما في علامات الاقتباس الأحادية، أو الثنائية أو الفاصلة العليا المائلة:
let single = 'single-quoted';
let double = "double-quoted";
let backticks = `backticks`;
علامات التنصيص الفردية والثنائية تكون متماثلة. أما الفاصلة العليا المائلة، فَتُتيح لنا تضمين أي تعبير في السلسلة النصية، عبر تضمينها في ${…}:
function sum(a, b) {
return a + b;
}
alert(`1 + 2 = ${sum(1, 2)}.`); // 1 + 2 = 3.
الميزة الأخرى لاستخدام الفاصلة العلوية المائلة هي إمكانية فصل السلسلة النصية إلى عدة أسطر:
let guestList = `Guests:
* John
* Pete
* Mary
`;
alert(guestList); // قائمة بالضيوف في أسطر منفصلة
يبدو الأمر طبيعيًا أليس كذلك؟ لكن علامات التنصيص الفردية والثنائية لا تعمل بهذه الطريقة. إن حاولنا استخدامها في نص متعدد الأسطر، سنحصل على خطأ:
let guestList = "Guests: // Error: Unexpected token ILLEGAL
* John";
أتى استخدام علامات الاقتباس الفردية والثنائية في أوقات مبكرة من إنشاء اللغة، عندما لم يُؤخَذ بالحسبان الحاجة إلى نص متعدد الأسطر. ظهرت الفاصلة العلوية المائلة مؤخرًا ولذا فإنها متعددة الاستعمالات.
Backticks also allow us to specify a “template function” before the first backtick. The syntax is: func`string`. The function func is called automatically, receives the string and embedded expressions and can process them. This is called “tagged templates”. This feature makes it easier to implement custom templating, but is rarely used in practice. You can read more about it in the manual.
الرموز الخاصة
ما زال بالإمكان كتابة نصوص متعددة الأسطر باستخدام علامات الاقتباس الأحادية والثنائية باستخدام ما يسمى ب “رمز السطر الجديد”، والذي يُكتَب \n، ويرمز لسطر جديد:
let guestList = "Guests:\n * John\n * Pete\n * Mary";
alert(guestList); // قائمة متعددة الأسطر بالضيوف
مثلًا، السطرين التاليين متماثلان، لكنهما مكتوبين بطريقة مختلفة:
let str1 = "Hello\nWorld"; // سطران باستخدام "رمز السطر الجديد"
// سطران باستخدام سطر جديد عادي والفواصل العليا المائلة
let str2 = `Hello
World`;
alert(str1 == str2); // true
يوجد رموز خاصة أخرى أقل انتشارًا.
هذه القائمة كاملة:
| المحرف | الوصف |
|---|---|
\n |
محرف السطر الجديد (Line Feed). |
\r |
محرف العودة إلى بداية السطر (Carriage Return)، ولا يستخدم بمفرده. تستخدم ملفات ويندوز النصية تركيبة من رمزين \r\n لتمثيل سطر جديد. |
'\ , "\ |
علامة اقتباس مزدوجة ومفردة. |
\\ |
شرطة مائلة خلفية |
\t |
مسافة جدولة “Tab” |
\b, \f, \v |
فراغ خلفي (backspace)، محرف الانتقال إلى صفحة جديد (Form Feed)، مسافة جدولة أفقية (Vertical Tab) على التوالي – تُستعمَل للتوافق، ولم تعد مستخدمة. |
\xXX |
صيغة رمز يونيكود مع عدد ست عشري مُعطى XX، مثال: ' \x7A' هي نفسها 'z'. |
\uXXXX |
صيغة رمز يونيكود مع عدد ست عشرية XXXX في تشفير UTF-16، مثلًا، \u00A9 – هو اليونيكود لرمز حقوق النسخ ©. يجب أن يكون مكون من 6 خانات ست عشرية. |
\u{X…XXXXXX} |
(1 إلى 6 أحرف ست عشرية) رمز يونيكود مع تشفير UTF-32 المعطى. تُشَفَّر بعض الرموز الخاصة برمزي يونيكود، فتأخذ 4 بايت. هكذا يمكننا إدخال شيفرات طويلة. |
| Character | Description |
|---|---|
\n |
New line |
\r |
Carriage return: not used alone. Windows text files use a combination of two characters \r\n to represent a line break. |
\', \" |
Quotes |
\\ |
Backslash |
\t |
Tab |
\b, \f, \v |
Backspace, Form Feed, Vertical Tab – kept for compatibility, not used nowadays. |
\xXX |
Unicode character with the given hexadecimal Unicode XX, e.g. '\x7A' is the same as 'z'. |
\uXXXX |
A Unicode symbol with the hex code XXXX in UTF-16 encoding, for instance \u00A9 – is a Unicode for the copyright symbol ©. It must be exactly 4 hex digits. |
\u{X…XXXXXX} (1 to 6 hex characters) |
A Unicode symbol with the given UTF-32 encoding. Some rare characters are encoded with two Unicode symbols, taking 4 bytes. This way we can insert long codes. |
Examples with Unicode:
alert( "\u00A9" ); // ©
alert( "\u{20331}" ); // 佫, a rare Chinese hieroglyph (long Unicode)
alert( "\u{1F60D}" ); // 😍, a smiling face symbol (another long Unicode)
// (رمز نادر من الهيروغليفية الصينية (يونيكود طويل alert( “\u{20331}” ); // 佫
// (رمز وجه مبتسم (يونيكود طويل آخر alert( “\u{1F60D}” ); // 😍
لاحظ بدء جميع الرموز الخاصة بشرطة مائلة خلفية `\`. تدعى أيضا ب "محرف التهريب" (escape character). يمكننا استخدامها أيضًا إن أردنا تضمين علامة اقتباس في النص: مثلًا:
```js run
alert( 'I\'m the Walrus!' ); // I'm the Walrus!
يجب إلحاق علامة الاقتباس الداخلية بالشرطة المائلة الخلفية \'، وإلا فستُعتَبر نهاية السلسلة النصية. لاحظ أن الشرطة المائلة الخلفية \ تعمل من أجل تصحيح قراءة السلسلة النصية بواسطة JavaScript. ومن ثم تختفي، لذا فإن النص في الذاكرة لا يحتوي على \. يمكننا رؤية ذلك بوضوح باستخدام alert على المثال السابق.
Of course, only the quotes that are the same as the enclosing ones need to be escaped. So, as a more elegant solution, we could switch to double quotes or backticks instead:
alert( `I'm the Walrus!` ); // I'm the Walrus!
لكن ماذا إن أردنا عرض شرطة مائلة خلفية ضمن النص؟ يمكن ذلك، لكننا نحتاج إلى تكرارها هكذا \\:
alert( `The backslash: \\` ); // The backslash: \
طول النص
تحمل الخاصية length طول النص:
alert( `My\n`.length ); // 3
لاحظ أن n\ هو رمز خاص، لذا يكون طول السلسلة الفعلي هو 3.
length هي خاصيةيُخطِئ بعض الأشخاص ذوي الخلفيات بلغات برمجية أخرى و يستدعون str.length() بدلًا من استدعاء str.length فقط. لذا لا يعمل هذا التابع لعدم وجوده. فلاحظ أن str.length هي خاصية عددية، وليس تابعًا ولا حاجة لوضع قوسين بعدها.
الوصول إلى محارف سلسلة
للحصول على حرف في مكان معين من السلسلة النصية pos، استخدم الأقواس المعقوفة [pos] أو استدعِ التابع str.charAt(pos). يبدأ أول حرف في الموضع رقم صفر:
let str = `Hello`;
// the first character
alert( str[0] ); // H
alert( str.charAt(0) ); // H
// the last character
alert( str[str.length - 1] ); // o
الأقواس المعقوفة هي طريقة جديدة للحصول على حرف، بينما التابع charAt موجود لأسباب تاريخية. الاختلاف الوحيد بينهما هو إن لم تجد الأقواس المربعة [] الحرف تُرجِع القيمة undefined بينما يُرجِع charAt نصًا فارغًا:
let str = `Hello`;
alert( str[1000] ); // undefined
alert( str.charAt(1000) ); // '' (سلسلة نصية فارغ)
يمكننا أيضا التنقل خلال جميع محارف سلسلة باستخدام for..of:
for (let char of "Hello") {
alert(char); // H,e,l,l,o (char becomes "H", then "e", then "l" etc)
}
النصوص ثابتة
لا يمكن تغيير النصوص في JavaScript، فمن المستحيل تغيير حرف داخل سلسلة نصية فقط. لنجرب الأمر للتأكد من أنه لن يعمل:
let str = 'Hi';
str[0] = 'h'; // خطأ
alert( str[0] ); // لا تعمل
الطريقة المعتادة هي إنشاء نص جديد وإسناده للمتغير str بدلًا من النص السابق. مثلًا:
let str = 'Hi';
str = 'h' + str[1]; // تستبدل كامل السلسلة النصية
alert( str ); // hi
سنرى المزيد من الأمثلة عن ذلك في الأجزاء التالية.
تغيير حالة الأحرف الأجنبية
يقوم التابع toLowerCase() والتابع toUpperCase() بِتغيير حالة الأحرف الأجنبية:
alert( 'Interface'.toUpperCase() ); // INTERFACE
alert( 'Interface'.toLowerCase() ); // interface
أو إن أردنا بتغيير حالة حرف واحد فقط:
alert( 'Interface'[0].toLowerCase() ); // 'i'
البحث عن جزء من النص
يوجد العديد من الطرق للبحث عن جزء من النص ضمن السلسلة النصية.
str.indexOf
التابع الأول هو str.indexOf(substr, pos).
يبحث التابع عن substr في str بدءًا من الموضع المحدد pos، ثم يُرجِع الموضع الذي تطابق مع النص أو يُرجِع -1 إن لم تعثر على تطابق. مثلًا:
let str = 'Widget with id';
alert( str.indexOf('Widget') ); // 0, because 'Widget' is found at the beginning
alert( str.indexOf('widget') ); // -1, not found, the search is case-sensitive
alert( str.indexOf("id") ); // 1, "id" is found at the position 1 (..idget with id)
The optional second parameter allows us to start searching from a given position.
For instance, the first occurrence of "id" is at position 1. To look for the next occurrence, let’s start the search from position 2:
let str = 'Widget with id';
alert( str.indexOf('id', 2) ) // 12
إن كنت مهتمًا بجميع المواضع التي يظهر فيها نص معين، يمكنك استخدام indexOf في حلقة. يتم كل استدعاء جديد من الموضِع التالي لِلموضع السابق الذي تطابق مع النص:
let str = 'As sly as a fox, as strong as an ox';
let target = 'as'; // let's look for it
let pos = 0;
while (true) {
let foundPos = str.indexOf(target, pos);
if (foundPos == -1) break;
alert( `Found at ${foundPos}` );
pos = foundPos + 1; // continue the search from the next position
}
يمكن تقصير الخوارزمية:
let str = "As sly as a fox, as strong as an ox";
let target = "as";
let pos = -1;
while ((pos = str.indexOf(target, pos + 1)) != -1) {
alert( pos );
}
str.lastIndexOf(substr, position)يوجد أيضًا تابع مشابه str.lastIndexOf(substr, position) والذي يبدأ البحث من نهاية السلسلة النصية حتى بدايتها. أي أنه يعيد موضع ظهور النص المبحوث عنه انطلاقًا من نهاية السلسلة.
يوجد خلل طفيف عند استخدام indexOf في if. فلا يمكن وضعها بداخل if بالطريقة التالية:
let str = "Widget with id";
if (str.indexOf("Widget")) {
alert("We found it"); // لا تعمل!
}