المواد ، الجزء الأول من الترجمة التي ننشرها اليوم ، مكرسة لميزات JavaScript القياسية الجديدة التي تمت مناقشتها في مؤتمر
Google I / O 2019 . على وجه الخصوص ، هنا سنتحدث عن التعبيرات المعتادة ، حول حقول الفصل ، حول العمل بالسلاسل.

الشيكات التعبير العادية
التعبيرات العادية (التعبير العادي ، اختصارًا - RegEx أو RegExp) هي تقنية قوية لمعالجة السلسلة يتم تنفيذها في العديد من لغات البرمجة. تعد التعبيرات العادية مفيدة للغاية في الحالات التي تحتاج فيها ، على سبيل المثال ، للبحث عن أجزاء من السلاسل النصية المعقدة. حتى وقت قريب ، كان لتطبيق جافا سكريبت التعبيرات العادية كل شيء باستثناء lookbackhinds.
من أجل فهم ماهية الفحص بأثر رجعي ، دعونا نتحدث أولاً عن رؤوس النظافة المدعومة بالفعل في JavaScript.
→
الجزء الثاني▍ الاختيار المسبق
يسمح لك بناء جملة الشيكات البادئة في التعبيرات العادية بالبحث عن أجزاء من السلاسل عندما يكون معروفًا أن الأجزاء الأخرى على يمينها. على سبيل المثال ، عند العمل مع السلسلة
MangoJuice, VanillaShake, GrapeJuice
يمكنك استخدام بناء جملة الاختيار الإيجابي الإيجابي للعثور على الكلمات التي تليها مباشرة كلمة
Juice
. في حالتنا ، هذه هي الكلمات
Mango
Grape
.
هناك نوعان من الشيكات الرائدة. هذه هي المظاهر الإيجابية والمظاهر السلبية.
الاختيار يؤدي الإيجابية
يتم استخدام فحص بادئة إيجابية للبحث عن خطوط إلى اليمين منها خطوط أخرى معروفة سابقًا. إليك ما يبدو عليه بناء جملة التعبير المعتاد المستخدم في هذا الفحص:
/[a-zA-Z]+(?=Juice)/
يسمح لك هذا القالب بتحديد الكلمات التي تتكون من أحرف صغيرة أو كبيرة ، متبوعة بكلمة
Juice
. لا تخلط بين الهياكل التي تصف عمليات الفحص الرائدة والاستعادية مع مجموعات الالتقاط. على الرغم من أن شروط هذه الشيكات مكتوبة بين قوسين ، فإن النظام لا يلتقطها. دعونا نلقي نظرة على مثال لفحص إيجابي للرصاص.
const testString = "MangoJuice, VanillaShake, GrapeJuice"; const testRegExp = /[a-zA-Z]+(?=Juice)/g; const matches = testString.match( testRegExp ); console.log( matches );
تحقق الرصاص السلبي
إذا أخذنا في الاعتبار ، باستخدام السطر أعلاه ، آلية عمل الفحوصات السلبية الأولية ، اتضح أنها تسمح لك بالعثور على الكلمات التي ليس لها كلمة
Juice
. يشبه بناء الجملة الشيكات السالبة بناء جملة الشيكات الإيجابية. ومع ذلك ، هناك ميزة واحدة فيه ، وهي أن الرمز
=
(يساوي) يتغير إلى رمز
!
(علامة التعجب). إليك ما يبدو عليه:
/[a-zA-Z]+(?!Juice)/
يسمح لك هذا التعبير المنتظم بتحديد كل الكلمات الموجودة على اليمين والتي لا توجد بها كلمة
Juice
. ولكن عند تطبيق مثل هذا القالب ، سيتم اختيار كل الكلمات الموجودة في السطر (
MangoJuice, VanillaShake, GrapeJuice
). والحقيقة هي أنه وفقًا للنظام ، لا توجد كلمة واحدة هنا تنتهي بـ
Juice
. نتيجة لذلك ، من أجل تحقيق النتيجة المرجوة ، تحتاج إلى توضيح التعبير العادي وإعادة كتابته مثل هذا:
/(Mango|Vanilla|Grape)(?!Juice)/
يتيح لك استخدام هذا القالب تحديد الكلمات
Mango
أو
Vanilla
أو
Grape
، وبعدها لا توجد كلمة
Juice
. هنا مثال:
const testString = "MangoJuice, VanillaShake, GrapeJuice"; const testRegExp = /(Mango|Vanilla|Grape)(?!Juice)/g; const matches = testString.match( testRegExp ); console.log( matches );
Check تحقق بأثر رجعي
قياسًا على بناء جملة الاختبارات الأولية ، يتيح لك بناء الجملة لعمليات التحقق بأثر رجعي تحديد تسلسل من الأحرف فقط إذا كان على يسار هذه التسلسلات نمط معين. على سبيل المثال ، عند معالجة السلسلة
FrozenBananas, DriedApples, FrozenFish
يمكننا استخدام فحص استعادي إيجابي للعثور على الكلمات الموجودة على اليسار والتي توجد بها الكلمة
Frozen
. في حالتنا ، تتوافق عبارة "
Bananas
Fish
مع هذا الشرط.
هناك ، كما هو الحال مع الشيكات الرائدة ، اختبارات إيجابية بأثر رجعي (نظرة إيجابية إلى الوراء) وشيكات بأثر رجعي سلبية (نظرة سلبية أو سلبية).
مراجعة بأثر رجعي إيجابية
يتم استخدام الاختبارات الإيجابية بأثر رجعي للبحث عن أنماط إلى اليسار منها أنماط أخرى. فيما يلي مثال على بناء الجملة المستخدم لوصف مثل هذه الاختبارات:
/(?<=Frozen)[a-zA-Z]+/
<
استخدام الرمز
<
هنا ، والذي لم يكن في وصف الشيكات الرائدة. بالإضافة إلى ذلك ، فإن الشرط في التعبير العادي لا يقع على يمين القالب الذي يهمنا ، ولكن إلى اليسار. باستخدام القالب أعلاه ، يمكنك تحديد جميع الكلمات التي تبدأ بـ
Frozen
. النظر في مثال:
const testString = "FrozenBananas, DriedApples, FrozenFish"; const testRegExp = /(?<=Frozen)[a-zA-Z]+/g; const matches = testString.match( testRegExp ); console.log( matches );
التحقق بأثر رجعي السلبي
تتيح لك آلية عمليات الفحص بأثر رجعي السلبية البحث عن الأنماط الموجودة في الخطوط التي ليس لها نمط محدد. على سبيل المثال ، إذا كنت بحاجة إلى تحديد الكلمات التي لا تبدأ بـ
Frozen
في
FrozenBananas, DriedApples, FrozenFish
، فيمكنك محاولة استخدام هذا التعبير العادي:
/(?<!Frozen)[a-zA-Z]+/
ولكن بما أن استخدام هذا البناء سيؤدي إلى اختيار كل الكلمات من السلسلة ، حيث أن أيا منها يبدأ بـ
Frozen
، يجب توضيح التعبير العادي:
/(?<!Frozen)(Bananas|Apples|Fish)/
هنا مثال:
const testString = "FrozenBananas, DriedApples, FrozenFish"; const testRegExp = /(?<!Frozen)(Bananas|Apples|Fish)/g; const matches = testString.match( testRegExp ); console.log( matches );
→ الدعم
سيقدم هذا القسم والأقسام المشابهة الأخرى معلومات عن مرحلة تنسيق الميزات الموصوفة لـ JS في اللجنة الفنية 39 (اللجنة الفنية 39 ، TC39) ، المسؤولة في ECMA International عن دعم مواصفات ECMAScript. ستوفر هذه الأقسام أيضًا بيانات حول إصدارات Chrome و Node.js (وأحيانًا على إصدار Firefox) ، بدءًا من ذلك يمكنك استخدام الميزات المقابلة.
حقول الصف
حقل الفئة عبارة عن بناء جملة جديد يستخدم لتحديد خصائص مثيلات الفئة (كائنات) خارج مُنشئ الفصل. هناك نوعان من حقول الفصل: حقول الفئة العامة وحقول الفصل الخاص.
class حقول الطبقة العامة
حتى وقت قريب ، كان يجب تحديد خصائص الكائنات داخل مُنشئ الفصل. هذه الخصائص كانت عامة (عامة). هذا يعني أنه يمكن الوصول إليهم عن طريق العمل مع مثيل للفئة (الكائن). فيما يلي مثال لإعلان ملكية عامة:
class Dog { constructor() { this.name = 'Tommy'; } }
عندما كان من الضروري إنشاء فصل من شأنه أن يمدد فئة معينة من الوالدين ، كان من الضروري استدعاء
super()
في مُنشئ الفصل الفرعي. كان يجب القيام بذلك قبل إضافة خصائصه الخاصة إلى الفصل الفرعي. إليك ما يبدو عليه:
class Animal {} class Dog extends Animal { constructor() { super();
بفضل ظهور بناء جملة الحقول العامة للفصل الدراسي ، من الممكن وصف حقول الفصل خارج المنشئ. سيقوم النظام بإجراء مكالمة ضمنية إلى
super()
.
class Animal {} class Dog extends Animal { sound = 'Woof! Woof!';
عند استدعاء
super()
ضمنيًا ، يتم تمرير جميع الوسائط التي يوفرها المستخدم عند إنشاء مثيل فئة (هذا هو سلوك JavaScript القياسي ، لا يوجد شيء خاص حول حقول الفئة الخاصة). إذا كان مُنشئ الفئة الأصل يحتاج إلى وسيطات تم إعدادها بطريقة خاصة ، فأنت بحاجة إلى الاتصال بـ
super()
بنفسك. ألق نظرة على نتائج استدعاء المنشئ الضمني للفئة الأصل عند إنشاء مثيل للفئة الفرعية.
class Animal { constructor( ...args ) { console.log( 'Animal args:', args ); } } class Dog extends Animal { sound = 'Woof! Woof!';
class حقول الصف الخاص
كما تعلمون ، في JavaScript لا توجد معدّلات وصول إلى حقول الفصل مثل
public
أو
private
أو
protected
. جميع خصائص الكائنات عامة بشكل افتراضي. هذا يعني أن الوصول إليهم غير محدود. إن الأقرب إلى إجراء خاصية لكائن مماثل للخاصية هو استخدام نوع بيانات
Symbol
. هذا يسمح لك بإخفاء خصائص الكائنات من العالم الخارجي. ربما تكون قد استخدمت أسماء خصائص مسبوقة بـ
_
(تسطير سفلي) للإشارة إلى أنه ينبغي اعتبار الخصائص المطابقة مخصصة للاستخدام فقط داخل الكائن. ومع ذلك ، هذا مجرد نوع من الإخطار لأولئك الذين سيستخدمون المنشأة. هذا لا يحل مشكلة التقييد الحقيقي للوصول إلى العقارات.
بفضل آلية الحقول الخاصة للفئات ، يمكن إتاحة خصائص الفصل داخل هذه الفئة فقط. هذا يؤدي إلى حقيقة أنه لا يمكن الوصول إليها من الخارج والعمل مع مثيل للفئة (الكائن). خذ المثال السابق وحاول الوصول إلى خاصية الفئة من الخارج عند استخدام البادئة.
class Dog { _sound = 'Woof! Woof!';
كما ترى ، فإن استخدام البادئة
_
لا يحل مشكلتنا. يمكن الإعلان عن الحقول الخاصة بالفئات بنفس طريقة الحقول العامة ، ولكن بدلاً من بادئة في شكل تسطير سفلي ، يجب إضافة بادئة في شكل علامة الجنيه (
#
) إلى أسمائها. محاولة الوصول غير المصرح به إلى الخاصية الخاصة للكائن المعلنة بهذه الطريقة ستؤدي إلى حدوث الخطأ التالي:
SyntaxError: Undefined private field
هنا مثال:
class Dog { #sound = 'Woof! Woof!';
لاحظ أنه لا يمكن الوصول إلى الممتلكات الخاصة إلا من الفصل الذي تم إعلانها فيه. نتيجة لذلك ، لا يمكن استخدام الفئات المنحدرة مباشرةً خصائص مشابهة للفئة الأصل.
يمكن الإعلان عن الحقول الخاصة (والعامة) دون كتابة قيم معينة فيها:
class Dog { #name; constructor( name ) { this.#name = name; } showName() { console.log( this.#name ); } }
→ الدعم
أسلوب السلسلة .matchAll ()
يحتوي النموذج الأولي لنوع بيانات
String
على طريقة
.match()
تقوم بإرجاع صفيف من أجزاء السلسلة التي تطابق الشرط المحدد بواسطة التعبير العادي. هنا مثال باستخدام هذه الطريقة:
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /([A-Z0-9]+)/g; console.log( colors.match( matchColorRegExp ) );
عند استخدام هذه الطريقة ، لا يتم إعطاء معلومات إضافية (مثل الفهارس) حول الأجزاء الموجودة في السلسلة. إذا قمت بإزالة علامة
g
من التعبير العادي الذي تم تمريره إلى طريقة
.match()
، فسوف
.match()
صفيفًا يحتوي على معلومات إضافية حول نتائج البحث. ومع ذلك ، مع هذا النهج ، سيتم العثور على الجزء الأول فقط من السلسلة المطابقة للتعبير العادي.
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/; console.log( colors.match( matchColorRegExp ) );
للحصول على شيء مشابه ، ولكن بالنسبة للعديد من أجزاء السلسلة ، يجب عليك استخدام طريقة التعبير العادية
.exec()
. تعتبر الإنشاءات اللازمة لهذا الأمر أكثر تعقيدًا من الإنشاءات التي سيتم فيها استخدام طريقة سلسلة مفردة للحصول على نتائج مماثلة. على وجه الخصوص ، نحتاج هنا
while
ستنفذ حتى
.exec()
بإرجاع
null
. باستخدام هذا النهج ، ضع في اعتبارك أن
.exec()
لا
.exec()
.
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/g;
لحل هذه المشكلات ، يمكننا الآن استخدام طريقة السلسلة
.matchAll()
، والتي تُرجع
.matchAll()
.
.next()
كل استدعاء إلى الأسلوب
.next()
من هذا التكرار العنصر التالي من نتائج البحث. نتيجة لذلك ، يمكن إعادة كتابة المثال أعلاه على النحو التالي:
const colors = "#EEE, #CCC, #FAFAFA, #F00, #000"; const matchColorRegExp = /#([A-Z0-9]+)/g; console.log( ...colors.matchAll( matchColorRegExp ) );
→ الدعم
المجموعات المسماة في التعبيرات العادية
يختلف مفهوم المجموعات في تطبيق جافا سكريبت لآليات التعبير العادية قليلاً عن تطبيق مفهوم مماثل بلغات أخرى. وهي ، عند استخدام جافا سكريبت ، يتم وضع قالب RegEx بين قوسين (باستثناء عندما يتم استخدام الأقواس في عمليات الفحص بأثر رجعي أو الاختبارات المتقدمة) ، يصبح القالب مجموعة.
سوف تنعكس شظايا السلسلة التي استولت عليها المجموعة في نتائج تطبيق التعبير العادي.
في المثال السابق ، يمكنك أن ترى أن العنصر الأول للصفيف مع نتائج البحث هو العنصر الذي يطابق التعبير العادي بأكمله ، والثاني هو الذي يتوافق مع المجموعة. هذا هو عنصر الصفيف:
["#EEE", "EEE", index: 0, input: "<colors>"]
إذا كانت هناك عدة مجموعات في التعبير العادي ، فسوف تدخل في نتائج معالجة السلسلة بترتيب وصفها في التعبير العادي. النظر في مثال:
const str = "My name is John Doe."; const matchRegExp = /My name is ([az]+) ([az]+)/i; const result = str.match( matchRegExp );console.log( result );
هنا يمكنك أن ترى أن السطر الأول من الإخراج هو السطر بأكمله الموافق للتعبير العادي. يمثل العنصران الثاني والثالث ما تم التقاطه بواسطة المجموعات.
يتيح لك استخدام المجموعات المسماة حفظ المجموعات التي تلتقطها داخل كائن
groups
، والتي تتوافق أسماء ممتلكاتها مع الأسماء المعينة للمجموعات.
const str = "My name is John Doe."; const matchRegExp = /My name is (?<firstName>[az]+) (?<lastName>[az]+)/i; const result = str.match( matchRegExp ); console.log( result ); console.log( result.groups );
تجدر الإشارة إلى أن المجموعات المسماة تعمل بشكل جيد مع طريقة
.matchAll()
.
→ الدعم
أن تستمر ...
أعزائي القراء! هل استخدمت أيًا من ابتكارات JavaScript الموضحة هنا؟
