Skip to content

6. سلاسل الأحرف

تشبه سلاسل الأحرف في جافا سكريبت إلى حد كبير تلك الموجودة في PHP.

Image

6.1. نص برمجي [str-01]

أول شيء يجب فهمه هو أنه بمجرد إنشاء سلسلة، لا يمكن تعديلها. هناك العديد من الطرق لإنشاء سلسلة جديدة من السلسلة الأصلية، لكن هذه الأخيرة تظل دون تغيير. علاوة على ذلك، يمكن أن تكون سلسلة الأحرف من نوعين:

  • [string] عندما يتم تهيئتها بسلسلة حرفية؛
  • [object] عندما يتم إنشاؤها كمثيل لفئة [String]؛

'use strict';

// سلاسل الأحرف هي للقراءة فقط (لا يمكن تعديلها)

// سلسلة
const chaîne1 = "abcd ";
// نوع
console.log("typeof(chaîne1)=", typeof (chaîne1));
// الحرف رقم 2
console.log("chaîne1[2]=", chaîne1[2]);
// يؤدي إلى حدوث خطأ
chaîne1[2] = "0";

التنفيذ


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Temp\19-09-01\javascript\strings\str-01.js"
typeof(chaîne1)= string
chaîne1[2]= c
c:\Temp\19-09-01\javascript\strings\str-01.js:1
TypeError: Cannot assign to read only property '2' of string 'abcd '
at Object.<anonymous> (c:\Temp\19-09-01\javascript\strings\str-01.js:12:12)
at Generator.next (<anonymous>)

6.2. نص برمجي [str-02]

يوضح هذا البرنامج النصي أنه يمكن إنشاء سلسلة أحرف بطريقتين.


'use strict';

// يمكن أن تكون سلاسل الأحرف من نوعين

// سلسلة حرفية
const chaîne1 = "abcd ";
// نوع
console.log("typeof(chaîne1)=", typeof (chaîne1));
// مثيل String
const chaîne2 = new String("xyzt");
// النوع
console.log("typeof(chaîne2)=", typeof (chaîne2));
// كتابة أخرى (بدون new) – النوع [string] وليس [object]
const chaîne3 = String("12 34");
// النوع
console.log("typeof(chaîne3)=", typeof (chaîne3));
// يوفر النوع [string] والنوع [object] نفس الطرق، وهي طرق فئة String
console.log("chaîne1.length=", chaîne1.length);
console.log("chaîne2.length=", chaîne2.length);

تعليقات

  • السطر 6: الطريقة المعتادة لتعريف سلسلة. سيكون [chaîne1] من النوع [string]؛
  • السطر 10: يمكن إنشاء سلسلة باستخدام منشئ الفئة [String]. سيكون [chaîne2] من النوع [object

التنفيذ


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\strings\str-02.js"
typeof(chaîne1)= string
typeof(chaîne2)= object
typeof(chaîne3)= string
chaîne1.length= 5
chaîne2.length= 4

يستفيد النوع [string] من أساليب الفئة [String].

6.3. نص برمجي [str-03]

يُظهر هذا البرنامج النصي سلسلة معينة مع استيفاء المتغيرات.


'use strict';

// سلسلة
const chaîne = "Introduction à Javascript par l'exemple";
// سلسلة مع استيفاء المتغيرات
const str = `[${chaîne}].substr(3, 2)=` + chaîne.substr(3, 2)
console.log(str);

تعليقات

  • السطر 6: من الممكن أن تحتوي سلاسل الأحرف على تعبيرات ${variable} التي يتم استبدالها بقيمة المتغير. نحن هنا في نفس منطق المتغيرات $ في سلاسل الأحرف PHP. يجب ملاحظة طريقة كتابة مثل هذه السلسلة: فهي محاطة بعلامة "backstick" أو الفاصلة المقلوبة (AltGr-7 على لوحة المفاتيح الفرنسية)؛

التنفيذ


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Temp\19-09-01\javascript\strings\tempCodeRunnerFile.js"
[Introduction à Javascript par l'exemple].substr(3, 2)=ro

6.4. نص برمجي [str-04]

لا تزال السلاسل التي تتضمن استبدال المتغيرات غير كافية. ففي الواقع، لا يمكن وضع تعبير بدلاً من المتغير في التعبير ${variable}. بالنسبة لمن لديهم خبرة في البرمجة بلغة C، لا يوجد ما يضاهي وظائف [printf, sprintf] لكتابة أو إنشاء سلاسل منسقة. قام المئات من المطورين بتطوير آلاف حزم جافا سكريبت التي تشكل نظامًا بيئيًا ضخمًا. عندما تكون هناك حاجة لا تلبيها جافا سكريبت أصلاً، يحين الوقت للبحث عن حزمة تلبيها. ولهذا الغرض، نستخدم مدير الحزم [npm]. يحتوي هذا المدير على خيار [search] الذي يسمح بالبحث عن سلسلة أحرف في وصف الحزم. يعرض [npm] قائمة بالحزم التي تطابق البحث. سنبحث إذن عن السلسلة [sprintf] في وصف الحزم:

Image

  • في العمود [4]، الكلمات الرئيسية للحزم الموجودة في العمود [3]؛
  • في العمود [5]، وصف الحزم الموجودة في العمود [3]؛

الخطوة التالية هي الانتقال إلى موقع الأداة [npm]، [https://www.npmjs.com/] وقراءة وصف الحزم:

Image

في [3]، نراجع قائمة الحزم ونختار واحدة منها.

Image

في وصف الحزمة، نجد المعلومات اللازمة لتثبيتها واستخدامها:

Image

نقوم بتثبيت الحزمة [sprintf-js] في محطة طرفية لـ [VSCode]:

Image

سيؤدي هذا التثبيت إلى تعديل الملف [package.json] الموجود في جذر المجلد [javascript] [2]:

Image

نرى أعلاه أن الحزمة قد تم تثبيتها في [dependencies]، أي في الحزم اللازمة لتنفيذ المشروع. يُذكر أن الحزم الضرورية توضع في [devDependencies] فقط أثناء تطوير المشروع. ولا يتم استخدامها أثناء التنفيذ. هذا الاختلاف مهم عند الحاجة إلى إنشاء النسخة النهائية من المشروع لوضعه في الإنتاج. توجد أدوات من أجل:

  • تجميع جميع ملفات jS الضرورية للتنفيذ في ملف واحد. وبالتالي، لا يتم تضمين حزم [devDependencies] في هذا الملف النهائي؛
  • تصغير حجم هذا الملف، أي جعل حجمه أصغر ما يمكن. ولهذا الغرض، على سبيل المثال، يتم حذف جميع التعليقات؛
  • "إخفاء" الكود لجعله صعب الفهم. على سبيل المثال، سيتم استبدال المتغيرات taux و salaire و impôt بمتغيرات a و b و c؛
  • إجراء تحسينات أخرى؛

يُستخدم هذا التحسين للملف النهائي لمشروع jS في برمجة الويب. قد تعتمد تطبيقات الويب على عدد كبير جدًا من ملفات جافا سكريبت. وقد يؤدي تحميل هذه الملفات بواسطة المتصفح إلى إبطاء عرض الصفحة الأولى للتطبيق. يهدف التحسين السابق إلى تحسين وقت التحميل هذا. إذا اعتبر المستخدمون أن وقت التحميل طويل جدًا، فلن يتم استخدام التطبيق.

الآن بعد أن أصبح لدينا الحزمة [sprintf-js]، علينا استخدامها. هذا هو البرنامج النصي [str-04]:


'use strict';
// استخدام حزمة خارجية للحصول على وظيفة sprintf
import { sprintf } from 'sprintf-js';
// سلسلة
const chaîne = "Introduction à Javascript par l'exemple";
// طريقة
console.log(sprintf("[%s].substr(3,2)=[%s]", chaîne, chaîne.substr(3, 2)));

مع ECMAScript 6، نستخدم الكلمة الرئيسية [import] لاستيراد كائن تم تصديره بواسطة حزمة. لمعرفة ما تصدره الحزمة، يمكننا الاطلاع على كودها:

Image

  • في [1]، انقر بزر الماوس الأيمن على الحزمة المستوردة؛
  • في [2]، نريد رؤية التعريف؛
  • في [3-4]، نرى أن الحزمة تصدر دالة تسمى [sprintf]؛

يتم استيراد الدالة [sprintf] من الحزمة [sprintf-js] باستخدام الأمر:


import { sprintf } from 'sprintf-js';

الكود الكامل:


'use strict';
// استخدام حزمة خارجية للحصول على وظيفة sprintf
import { sprintf } from 'sprintf-js';
// سلسلة
const chaîne = "Introduction à Javascript par l'exemple";
// طريقة
console.log(sprintf("[%s].substr(3,2)=[%s]", chaîne, chaîne.substr(3, 2)));

ينتج النتائج التالية:


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe "c:\Temp\19-09-01\javascript\strings\str-04.js"
c:\Temp\19-09-01\javascript\strings\str-04.js:3
import { sprintf } from 'sprintf-js';
^

SyntaxError: Unexpected token {
at new Script (vm.js:79:7)
at createScript (vm.js:251:10)
at Object.runInThisContext (vm.js:303:10)
at Module._compile (internal/modules/cjs/loader.js:657:28)

السطر 3، لم يتم فهم الأمر [import]. ويرجع ذلك إلى أن الإصدار 10.15.1 من [node.js] المستخدم في هذه الدورة (سبتمبر 2019) لا يتوافق بعد مع معيار ECMAScript لاستيراد الحزم التي تسمى الوحدات النمطية. في عام 2019، يتوافق [node.js] مع معيار للوحدات النمطية يُسمى CommonJS. ومن المقرر أن يتم دمج وحدات ECMAScript بواسطة [node.js] في عام 2020. ومرة أخرى، بدأ المطورون العمل وأنتجوا حزمًا تسمح باستخدام وحدات ES6 مع [node.js] اعتبارًا من الآن (2019).

سنستخدم حزمة تسمى [esm] (وحدات ECMAScript). نقوم بتثبيتها في محطة طرفية لمشروع [javascript]:

Image

في [4]، نلاحظ أن تثبيت الحزمة [esm] [1-3] قد عدّل الملف [javascript/package.json].

لم ننتهِ بعد. لكي يتم استخدام الوحدة النمطية [esm] بواسطة [node.js]، يجب تشغيل هذه الأخيرة مع الوسيطة [-r esm].

لذلك نقوم بتعديل تكوين الملحق [Code Runner] من [VSCode]:

Image

Image

في [11]، نضيف الحجة [-r esm] ونحفظ (Ctrl-S) التكوين.

الآن، يمكننا تشغيل البرنامج النصي [str-04]:


'use strict';
// استخدام حزمة خارجية للحصول على الدالة sprintf
import { sprintf } from 'sprintf-js';
// سلسلة
const chaîne = "Introduction à Javascript par l'exemple";
// طريقة substr
console.log(sprintf("[%s].substr(3,2)=[%s]", chaîne, chaîne.substr(3, 2)));

Image

6.5. البرنامج النصي [str-05]

فيما يلي ما تقوله الوثائق حول الوظيفة [sprintf]:

يتم تمييز العناصر النائبة في سلسلة التنسيق بعلامة % وتليها واحد أو أكثر من هذه العناصر، بالترتيب التالي:

  • رقم اختياري يتبعه علامة $ تحدد مؤشر الحجة الذي سيتم استخدامه للقيمة. إذا لم يتم تحديده، فسيتم وضع الحجج بنفس ترتيب العناصر النائبة في سلسلة الإدخال.
  • علامة + اختيارية تفرض وضع علامة زائد أو ناقص قبل النتيجة في القيم الرقمية. بشكل افتراضي، يتم استخدام علامة - فقط على الأرقام السالبة.
  • محدد حشو اختياري يحدد الحرف الذي سيتم استخدامه للحشو (إذا تم تحديده). القيم الممكنة هي 0 أو أي حرف آخر يسبقه علامة ' (علامة اقتباس مفردة). الإعداد الافتراضي هو الحشو بمسافات.
  • علامة - اختيارية، تجعل sprintf تقوم بمحاذاة نتيجة هذا العنصر النائب إلى اليسار. الإعداد الافتراضي هو محاذاة النتيجة إلى اليمين.
  • رقم اختياري، يحدد عدد الأحرف التي يجب أن تحتوي عليها النتيجة. إذا كانت القيمة المراد إرجاعها أقصر من هذا الرقم، فسيتم ملء الفراغات. عند استخدامه مع محدد النوع j (JSON)، يحدد طول الملء حجم علامة الجدولة المستخدمة للتبويب.
  • معدل دقة اختياري، يتكون من نقطة (.) متبوعة برقم، يحدد عدد الأرقام التي يجب عرضها للأرقام العائمة. عند استخدامه مع محدد النوع g، فإنه يحدد عدد الأرقام ذات الدلالة. عند استخدامه على سلسلة، فإنه يؤدي إلى اقتطاع النتيجة.
  • محدد نوع يمكن أن يكون أيًا مما يلي:
    • % — ينتج حرف % حرفي
    • b — ينتج عددًا صحيحًا كرقم ثنائي
    • c — ينتج عددًا صحيحًا كحرف بقيمة ASCII
    • d أو i — ينتج عددًا صحيحًا كرقم عشري موقّع
    • e — ينتج عددًا عائمًا باستخدام الترميز العلمي
    • u — ينتج عددًا صحيحًا كرقم عشري غير موقّع
    • f — تُنتج عددًا عائمًا كما هو؛ انظر الملاحظات حول الدقة أعلاه
    • g — ينتج عددًا عائمًا كما هو؛ انظر الملاحظات حول الدقة أعلاه
    • o — ينتج عددًا صحيحًا كرقم ثماني
    • s — ينتج سلسلة نصية كما هي
    • t — ينتج قيمة صحيحة أو خاطئة
    • T — ينتج نوع الحجة 1
    • v — يعطي القيمة الأولية للحجة المحددة
    • x — ينتج عددًا صحيحًا كرقم سداسي عشري (بالأحرف الصغيرة)
    • X — ينتج عددًا صحيحًا كرقم سداسي عشري (بالأحرف الكبيرة)
    • j — ينتج كائن JavaScript أو مصفوفة كسلسلة مشفرة بـ JSON

يستخدم البرنامج النصي [script-05] بعضًا من هذه التنسيقات:


'use strict';
// استخدام حزمة خارجية للحصول على الدالة sprintf
import { sprintf } from 'sprintf-js';
// سلسلة
const chaîne = "Javascript";
// سلاسل الأحرف
console.log(sprintf("[%s, %%s]=>[%s]", chaîne, chaîne));
console.log(sprintf("[%s, %%20s]=>[%20s]", chaîne, chaîne));
console.log(sprintf("[%s, %%-20s]=>[%-20s]", chaîne, chaîne));
// أعداد صحيحة
console.log(sprintf("[%d, %%d]=>[%d]", 10, 10));
console.log(sprintf("[%d, %%4d]=>[%4d]", 10, 10));
console.log(sprintf("[%d, %%-4d]=>[%-4d]", 10, 10));
console.log(sprintf("[%d, %%04d]=>[%04d]", 10, 10));
// أرقام حقيقية
console.log(sprintf("[%f, %%f]=>[%f]", -10.5, -10.5));
console.log(sprintf("[%f, %%10.2f]=>[%10.2f]", -10.5, -10.5));
console.log(sprintf("[%f, %%-10.2f]=>[%-10.2f]", -10.5, -10.5));
console.log(sprintf("[%f, %%010.3f]=>[%010.3f]", -10.5, -10.5));
// json
console.log(sprintf("personne (%%j)=%j", { nom: "mathieu", âge: 34 }));
// النوع
console.log(sprintf("type personne (%%T)=%T", { nom: "mathieu", âge: 34 }));
// منطقية
console.log(sprintf("booléen (%%t)=%t", 4 === 4));

التنفيذ


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\strings\str-05.js"
[Javascript, %s]=>[Javascript]
[Javascript, %20s]=>[ Javascript]
[Javascript, %-20s]=>[Javascript ]
[10, %d]=>[10]
[10, %4d]=>[ 10]
[10, %-4d]=>[10 ]
[10, %04d]=>[0010]
[-10.5, %f]=>[-10.5]
[-10.5, %10.2f]=>[ -10.50]
[-10.5, %-10.2f]=>[-10.50 ]
[-10.5, %010.3f]=>[-00010.500]
personne (%j)={"nom":"mathieu","âge":34}
type personne (%T)=object
booléen (%t)=true

6.6. البرنامج النصي [str-06]

يقدم البرنامج النصي [str-06] بعض طرق فئة [String] التي يمكن استخدامها أيضًا في النوع [string]:


'use strict';
// استخدام حزمة خارجية للحصول على دالة sprintf
import { sprintf } from 'sprintf-js';
// سلسلة
const chaîne = "  Introduction à Javascript ";
// بعض الطرق
// substr(10,2): حرفان بدءًا من الرقم 10
console.log(sprintf("[%s].substr(10,2)=[%s]", chaîne, chaîne.substr(10, 2)));
// trim: إزالة المسافات في بداية ونهاية السلسلة (المسافة=\b \t \r \n \f)
console.log(sprintf("[%s].trim()=[%s]", chaîne, chaîne.trim()));
// toLowerCase: تحويل إلى أحرف صغيرة
console.log(sprintf("[%s].toLowerCase=[%s]", chaîne, chaîne.toLowerCase()));
// toUpperCase: تحويل إلى أحرف كبيرة
console.log(sprintf("[%s].toUpperCase=[%s]", chaîne, chaîne.toUpperCase()));
// indexOf: موضع السلسلة المطلوبة  في السلسلة، -1 إذا كانت السلسلة الفرعية غير موجودة
console.log(sprintf("[%s].indexOf('Java')=[%s]", chaîne, chaîne.indexOf('Java')));
console.log(sprintf("[%s].trim().indexOf('abcd')=[%s]", chaîne, chaîne.indexOf('abcd')));
// includes: صحيح إذا كانت السلسلة المطلوبة موجودة في السلسلة
console.log(sprintf("[%s].includes('Java')=[%s]", chaîne, chaîne.includes('Java')));
// length: طول السلسلة - ليست طريقة بل خاصية
console.log(sprintf("[%s].length=[%s]", chaîne, chaîne.length));
// slice (7,10): سلاسل الأحرف من رقم 7 إلى 9
console.log(sprintf("[%s].slice(7,10)=[%s]", chaîne, chaîne.slice(7, 10)));
// match: يبحث عن تعبير في السلسلة - يمكن أن يكون هذا التعبير تعبيرًا عاديًا
// /intro/i: تعبير منتظم يشير إلى السلسلة [intro] بأحرف كبيرة أو صغيرة
// يعرض السلسلة التي تم العثور عليها
console.log(sprintf("[%s].match(/intro/i)=[%s]", chaîne, chaîne.match(/intro/i)));
// replace: يستبدل السلسلة 1 بالسلسلة 2 في السلسلة
// يستبدل أول ظهور لـ i بـ x
console.log(sprintf("[%s].replace('i','x')=[%s]", chaîne, chaîne.replace('i', 'x')));
// يستبدل جميع مرات ظهور i بـ x
// /i/g هو تعبير منتظم يشير إلى جميع (g) مرات ظهور i
console.log(sprintf("[%s].replace(/i/g,'x')=[%s]", chaîne, chaîne.replace(/i/g, 'x')));
// split: يقسم السلسلة إلى كلمات مفصولة بمعلمة split
// يعرض مصفوفة هذه الكلمات
// /\s*/: كلمات مفصولة بـ 0 أو أكثر من المسافات
console.log(sprintf("[%s].split(/\\s*/)=[%s]", chaîne, chaîne.split(/\s*/)));
// /\s+/: كلمات مفصولة بواحدة أو أكثر من المسافات
console.log(sprintf("[%s].split(/\\s+/)=[%s]", chaîne, chaîne.split(/\s+/)));

التنفيذ


[Running] C:\myprograms\laragon-lite\bin\nodejs\node-v10\node.exe -r esm "c:\Data\st-2019\dev\es6\javascript\strings\str-06.js"
[ Introduction à Javascript ].substr(10,2)=[ti]
[ Introduction à Javascript ].trim()=[Introduction à Javascript]
[ Introduction à Javascript ].toLowerCase=[ introduction à javascript ]
[ Introduction à Javascript ].toUpperCase=[ INTRODUCTION À JAVASCRIPT ]
[ Introduction à Javascript ].indexOf('Java')=[17]
[ Introduction à Javascript ].trim().indexOf('abcd')=[-1]
[ Introduction à Javascript ].includes('Java')=[true]
[ Introduction à Javascript ].length=[28]
[ Introduction à Javascript ].slice(7,10)=[duc]
[ Introduction à Javascript ].match(/intro/i)=[Intro]
[ Introduction à Javascript ].replace('i','x')=[ Introductxon à Javascript ]
[ Introduction à Javascript ].replace(/i/g,'x')=[ Introductxon à Javascrxpt ]
[ Introduction à Javascript ].split(/\s*/)=[,I,n,t,r,o,d,u,c,t,i,o,n,à,J,a,v,a,s,c,r,i,p,t,]
[ Introduction à Javascript ].split(/\s+/)=[,Introduction,à,Javascript,]