دليل JavaScript الجزء 9: نظرة عامة على معايير ES7 و ES8 و ES9

اليوم ، في الجزء التاسع من ترجمة دليل JavaScript ، سيتم تقديم نظرة عامة على الميزات التي ظهرت في اللغة بفضل معايير ES7 و ES8 و ES9.

الجزء 1: البرنامج الأول ، وميزات اللغة والمعايير
الجزء 2: نمط الرمز وهيكل البرنامج
الجزء 3: المتغيرات ، أنواع البيانات ، التعبيرات ، الأشياء
الجزء 4: الميزات
الجزء 5: المصفوفات والحلقات
الجزء 6: استثناءات ، فواصل منقوطة ، حرفي أحرف البدل
الجزء 7: الوضع الصارم ، هذه الكلمة الأساسية ، والأحداث ، والوحدات النمطية ، والحسابات الرياضية
الجزء 8: نظرة عامة على ميزات ES6
الجزء 9: نظرة عامة على معايير ES7 و ES8 و ES9



ES7 القياسية


تم إصدار معيار ES7 ، والذي يطلق عليه ES2016 ، وفقًا للمصطلحات الرسمية ، في صيف عام 2016. هو ، بالمقارنة مع ES6 ، أحضر إلى اللغة ليس جديدًا كثيرًا. على وجه الخصوص ، نحن نتحدث عن ما يلي:

  • طريقة Array.prototype.includes() .
  • مشغل الأس.

▍ طريقة Array.prototype.includes ()


تم Array.prototype.includes() الأسلوب Array.prototype.includes() للتحقق من وجود عنصر في الصفيف. العثور على المطلوب في الصفيف ، فإنه يعود true ، وليس العثور على - false . قبل ES7 ، تم استخدام طريقة indexOf() لتنفيذ نفس العملية ، والتي تُرجع ، في حالة العثور على عنصر ، أول فهرس يمكن العثور عليه في الصفيف. إذا لم يعثر indexOf() على العنصر ، فسوف يُرجع الرقم -1 .

وفقًا لقواعد تحويل نوع JavaScript ، -1 تحويل الرقم -1 إلى true . نتيجة لذلك ، للتحقق من نتائج تشغيل indexOf() يجب استخدام بنية غير ملائمة بشكل خاص من النموذج التالي.

 if ([1,2].indexOf(3) === -1) { console.log('Not found') } 

إذا كنت في موقف مشابه ، بافتراض أن indexOf() ، بدون العثور على عنصر ، ترجع false ، تستخدم شيئًا ما هو موضح أدناه ، فلن تعمل الشفرة بشكل صحيح.

 if (![1,2].indexOf(3)) { // console.log('Not found') } 

في هذه الحالة ، اتضح أن الإنشاء ![1,2].indexOf(3) يعطي false .

باستخدام الأسلوب includes() ، تبدو هذه المقارنات أكثر منطقية.

 if (![1,2].includes(3)) { console.log('Not found') } 

في هذه الحالة ، فإن البناء [1,2].includes(3) إرجاع false ، هذه القيمة هي عامل التشغيل ! يتحول إلى true وتتلقى وحدة التحكم رسالة تفيد بعدم العثور على العنصر في الصفيف.

operator مشغل الأس


ينفذ عامل التسوية نفس وظيفة طريقة Math.pow() ، ولكنه أكثر ملاءمة لاستخدامه من وظيفة المكتبة ، لأنه جزء من اللغة.

 Math.pow(4, 2) == 4 ** 2 //true 

يمكن اعتبار هذا المشغل إضافة لطيفة لـ JS ، وهو مفيد في التطبيقات التي تؤدي عمليات حسابية معينة. يوجد عامل مشابه في لغات البرمجة الأخرى.

معيار ES8


تم إصدار ES8 Standard (ES2017) في عام 2017. هو ، مثل ES7 ، لم يجلب الكثير للغة. وهي نتحدث عن الميزات التالية:

  • إضافة سلاسل إلى طول معين.
  • Object.values() .
  • Object.entries() .
  • Object.getOwnPropertyDescriptors() .
  • زائدة الفواصل في المعلمات وظيفة.
  • وظائف غير متزامنة.
  • العمل مع الذاكرة المشتركة والعمليات الذرية.

ding إضافة خطوط إلى طول معين


قدمت ES8 طريقتين جديدتين لكائن String - padStart() و padEnd() .

تملأ طريقة padStart() السطر الحالي بسطر آخر حتى يصل الخط النهائي إلى الطول المرغوب. يحدث التعبئة في بداية السطر (يسار). إليك كيفية استخدام هذه الطريقة.

 str.padStart(targetLength [, padString]) 

هنا str هي السطر الحالي ، targetLength هو طول السطر النهائي (إذا كان أقل من طول السطر الحالي ، فسيتم إرجاع هذا الخط بدون تغييرات) ، padString هو معلمة اختيارية - السطر المستخدم لملء السطر الحالي. إذا لم padString تحديد padString استخدام حرف المسافة لوضع الخط الحالي على الطول المحدد.

طريقة padEnd() تشبه padStart() ، ولكن يتم تعبئة السطر على اليمين.

النظر في أمثلة لاستخدام هذه الأساليب.

 const str = 'test'.padStart(10) const str1 = 'test'.padEnd(10,'*') console.log(`'${str}'`) //'      test' console.log(`'${str1}'`) //'test******' 

هنا ، عند استخدام padStart() مع الطول المرغوب للسلسلة الناتجة فقط ، تمت إضافة مسافات إلى بداية السلسلة الأصلية. عند استخدام padEnd() بطول السطر الأخير والخط المراد ملؤه ، تمت إضافة الأحرف * إلى نهاية السطر الأصلي.

▍ طريقة كائن القيم ()


تقوم هذه الطريقة بإرجاع صفيف يحتوي على قيم خصائص الكائن الخاصة ، أي تلك الخصائص التي يحتوي عليها الكائن نفسه ، وليس تلك الخصائص التي يمكن الوصول إليها من خلال سلسلة النموذج الأولي.

إليك كيفية استخدامه.

 const person = { name: 'Fred', age: 87 } const personValues = Object.values(person) console.log(personValues) // ['Fred', 87] 

تنطبق هذه الطريقة أيضًا على المصفوفات.

Object طريقة Object.entries ()


تقوم هذه الطريقة بإرجاع صفيف ، يكون كل عنصر منها عبارة عن صفيف يحتوي ، بالتنسيق [key, value] ، مفاتيح وقيم خصائص الكائن الخاصة.

 const person = { name: 'Fred', age: 87 } const personValues = Object.entries(person) console.log(personValues) // [['name', 'Fred'], ['age', 87]] 

عند تطبيق هذه الطريقة على المصفوفات ، يتم عرض مؤشرات العناصر كمفاتيح ، ويتم عرض ما يتم تخزينه في الصفيف في المؤشرات المقابلة كقيم.

▍ أسلوب getOwnPropertyDescriptors ()


تُرجع هذه الطريقة معلومات حول جميع خصائص الكائن. ترتبط مجموعات السمات (الواصفات) بخصائص الكائن. على وجه الخصوص ، نحن نتحدث عن السمات التالية:

  • value - قيمة خاصية الكائن.
  • writable - يحتوي على true إذا كان يمكن تغيير الخاصية.
  • يحتوي get - على وظيفة getter المرتبطة بالعقار ، أو ، إذا لم يكن هناك مثل هذه الوظيفة ، undefined .
  • set - يحتوي على وظيفة setter للخاصية أو undefined .
  • configurable - إذا كان false - لا يمكن حذف الخاصية ، لا يمكن تغيير سماتها باستثناء القيمة.
  • enumerable - إذا كانت true في هذه الخاصية - تكون قابلة للتعداد.

إليك كيفية استخدام هذه الطريقة.

 Object.getOwnPropertyDescriptors(obj) 

يتطلب الأمر كائنًا تحتاج إلى معرفة معلومات ممتلكاته وإرجاع كائن يحتوي على هذه المعلومات.

 const person = { name: 'Fred', age: 87 } const propDescr = Object.getOwnPropertyDescriptors(person) console.log(propDescr) /* { name:  { value: 'Fred',    writable: true,    enumerable: true,    configurable: true }, age:  { value: 87,    writable: true,    enumerable: true,    configurable: true } } */ 

لماذا هذه الطريقة مطلوبة؟ والحقيقة هي أنه يسمح لك بإنشاء نسخ صغيرة من الأشياء ، والنسخ ، بالإضافة إلى الخصائص الأخرى ، والأدوات ، والأدوات الثابتة. لا يمكن القيام بذلك باستخدام الأسلوب Object.assign() ، الذي ظهر في المعيار ES6 ، لنسخ الكائنات.

المثال التالي يحتوي على كائن مع setter يعرض ، باستخدام console.log() ، ما يحاولون الكتابة إلى خاصية المطابقة الخاصة به.

 const person1 = { set name(newName) {     console.log(newName) } } person1.name = 'x' // x 

دعنا نحاول نسخ هذا الكائن باستخدام طريقة assign() .

 const person2 = {} Object.assign(person2, person1) person2.name = 'x' //     ,    

كما ترون ، هذا النهج لا يعمل. يتم الآن تمثيل خاصية name ، التي تم تعيينها في الكائن الأصلي ، كخاصية عادية.

الآن سنقوم بنسخ الكائن باستخدام الأساليب Object.defineProperties() (ظهرت في ES5.1) و Object.getOwnPropertyDescriptors() .

 const person3 = {} Object.defineProperties(person3, Object.getOwnPropertyDescriptors(person1)) person3.name = 'x' //x 

يبقى الضابط هنا في نسخة الكائن.

تجدر الإشارة إلى أن القيود الخاصة بـ Object.assign() هي أيضًا من خصائص الأسلوب Object.create() عند استخدامها لاستنساخ الكائنات.

ple إكمال الفاصلة في معلمات الوظيفة


تتيح لك هذه الميزة ترك فاصلة في نهاية قائمة المعلمات أو الوسائط ، على التوالي ، عند الإعلان وعند استدعاء الوظائف.

 const doSomething = ( var1, var2, ) => { //... } doSomething( 'test1', 'test2', ) 

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

▍ وظائف غير متزامن


ظهر التصميم غير async/await المنتظر في معيار ES2017 ، والذي يمكن اعتباره أهم ابتكار في هذه النسخة من اللغة.

الدالات غير المتزامنة هي مزيج من الوعود والمولدات ؛ فهي تبسط الإنشاءات التي كانت تتطلب في السابق قدراً كبيراً من كود القالب وسلاسل الوعود غير الملائمة لوصفها. في الواقع ، نحن نتحدث عن تجريد رفيع المستوى على الوعود.

عندما ظهرت الوعود في معيار ES2015 ، فقد تم تصميمها لحل المشكلات الحالية مع الكود غير المتزامن ، وهو ما فعلوه. ولكن على مدار العامين اللذين شاركا في معايير ES2015 و ES2017 ، أصبح من الواضح أن الوعود لا يمكن اعتبارها الحل النهائي لهذه المشكلات.

على وجه الخصوص ، كانت الوعود تهدف إلى حل مشكلة "معاودة الاتصال في الجحيم" ، ولكن بعد حل هذه المشكلة ، لم يظهروا هم أنفسهم بأفضل ما لديهم بسبب تعقيد الكود الذي يتم استخدامه فيه. في واقع الأمر ، فإن البناء async/await يحل مشكلة الوعود ويحسن قابلية استخدام الشفرة غير المتزامنة.

النظر في مثال.

 function doSomethingAsync() { return new Promise((resolve) => {     setTimeout(() => resolve('I did something'), 3000) }) } async function doSomething() { console.log(await doSomethingAsync()) } console.log('Before') doSomething() console.log('After') 

هذا الكود سوف يخرج التالي إلى وحدة التحكم.

 Before After I did something 

كما ترون ، بعد الاتصال بـ doSomething() يستمر البرنامج في التشغيل ، وبعد Before يتم عرض "من Before ، After في وحدة التحكم ، وبعد مرور ثلاث ثوان ، I did something .

استدعاء دالة تسلسلية غير متزامن


إذا لزم الأمر ، يمكن أن تشكل الوظائف غير المتزامنة شيئًا مثل سلاسل المكالمات. تتميز هذه التصميمات بقراءة أفضل من أي شيء مشابه ، يعتمد فقط على الوعود. يمكن ملاحظة ذلك في المثال التالي.

 function promiseToDoSomething() { return new Promise((resolve)=>{     setTimeout(() => resolve('I did something'), 10000) }) } async function watchOverSomeoneDoingSomething() { const something = await promiseToDoSomething() return something + ' and I watched' } async function watchOverSomeoneWatchingSomeoneDoingSomething() { const something = await watchOverSomeoneDoingSomething() return something + ' and I watched as well' } watchOverSomeoneWatchingSomeoneDoingSomething().then((res) => { console.log(res) // I did something and I watched and I watched as well }) 

▍ الذاكرة المشتركة والعمليات الذرية


نحن هنا نتحدث عن كائن SharedArrayBuffer ، والذي يسمح لنا بوصف مناطق الذاكرة المشتركة ، وكائن Atomics ، الذي يحتوي على مجموعة من العمليات الذرية في شكل أساليب ثابتة. يمكن العثور هنا على تفاصيل حول الاحتمالات التي توفرها هذه الكائنات للمبرمج.

ES9 القياسية


ES9 (ES2018) هو أحدث إصدار من المعيار وقت نشر هذه المادة. وهنا ميزاته الرئيسية:

  • تطبيق انتشار والراحة البيانات على الكائنات.
  • تكرارات غير متزامنة.
  • طريقة Promise.prototype.finally() .
  • تحسينات التعبير العادية.

spread تطبيق انتشار وانتشار العوامل إلى الأشياء


لقد تحدثنا بالفعل عن مشغلي الراحة والانتشار الذي ظهر في ES6 ويمكن استخدامه للعمل مع المصفوفات. كلاهما يشبه ثلاث نقاط. المشغل الباقي ، في المثال التالي لتدمير مجموعة ، يتيح لك وضع عناصره الأولى والثانية في الثوابت first second ، والباقي في العناصر الثابتة others .

 const numbers = [1, 2, 3, 4, 5] const [first, second, ...others] = numbers console.log(first) //1 console.log(second) //2 console.log(others) //[ 3, 4, 5 ] 

يسمح لك عامل spread بتمرير المصفوفات إلى الوظائف التي تتوقع قوائم معلمات منتظمة.

 const numbers = [1, 2, 3, 4, 5] const sum = (a, b, c, d, e) => a + b + c + d + e const res = sum(...numbers) console.log(res) //15 

الآن ، باستخدام نفس الطريقة ، يمكنك العمل مع الكائنات. فيما يلي مثال لاستخدام جملة الراحة في عملية تخصيص مدمرة.

 const { first, second, ...others } = { first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } console.log(first) //1 console.log(second) //2 console.log(others) //{ third: 3, fourth: 4, fifth: 5 } 

فيما يلي بيان الحيز المستخدم عند إنشاء كائن جديد بناءً على كائن موجود. يستمر هذا المثال في المثال السابق.

 const items = { first, second, ...others } console.log(items) //{ first: 1, second: 2, third: 3, fourth: 4, fifth: 5 } 

التكرارات غير المتزامنة


يتيح لك التصميم الجديد for-await-of استدعاء وظائف غير متزامنة تقوم بإرجاع الوعود في حلقات. هذه الحلقات تنتظر حل الوعد قبل الانتقال إلى الخطوة التالية. هنا هو كيف يبدو.

 for await (const line of readLines(filePath)) { console.log(line) } 

في الوقت نفسه ، تجدر الإشارة إلى أن هذه الحلقات يجب أن تستخدم في وظائف غير متزامنة - بنفس الطريقة عند العمل مع إنشاء async/await .

▍ طريقة Promise.prototype.finally ()


إذا تم حل الوعد بنجاح ، then() استدعاء الطريقة التالية then() . إذا حدث خطأ ما ، يتم استدعاء أسلوب catch() . تتيح لك الطريقة finally() تنفيذ بعض التعليمات البرمجية بغض النظر عما حدث من قبل.

 fetch('file.json') .then(data => data.json()) .catch(error => console.error(error)) .finally(() => console.log('finished')) 

▍ تحسينات التعبير العادية


التعبيرات العادية لديها القدرة على التحقق بأثر رجعي من السلاسل ( ?<= ). يسمح لك هذا بالبحث عن بعض الإنشاءات في السطور التي توجد بها بعض الإنشاءات الأخرى.

القدرة على تسبق الشيكات باستخدام ?= كانت الإنشاءات موجودة في التعبيرات العادية التي تم تنفيذها في JavaScript قبل معيار ES2018. تتيح لك عمليات التحقق هذه معرفة ما إذا كان جزء آخر يتبع جزءًا معينًا من الخط.

 const r = /Roger(?= Waters)/ const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //false console.log(res2) //true 

البناء ?! ينفذ العملية المعاكسة - لن يتم العثور على تطابق إلا في حالة عدم اتباع خط آخر للسطر المحدد.

 const r = /Roger(?! Waters)/g const res1 = r.test('Roger is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //true console.log(res2) //false 

في التحقق بأثر رجعي ، كما ذكر بالفعل ، والبناء ?<= يستخدم.

 const r = /(?<=Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //false console.log(res2) //true 

يمكن إجراء العملية المقابلة لتلك الموصوفة باستخدام البناء ?<! .

 const r = /(?<!Roger) Waters/ const res1 = r.test('Pink Waters is my dog') const res2 = r.test('Roger is my dog and Roger Waters is a famous musician') console.log(res1) //true console.log(res2) //false 

يونيكود تسلسل هروب ريكس


في التعبيرات العادية ، يمكنك استخدام الفئة \d التي تتطابق مع أي رقم ، والفئة \s التي تطابق أي حرف مسافة بيضاء ، والفئة \w التي تتطابق مع أي حرف أبجدي رقمي ، وما إلى ذلك. تعمل الميزة المذكورة على توسيع مجموعة الفئات التي يمكن استخدامها في التعبيرات العادية ، مما يتيح لك العمل مع تسلسل Unicode. نحن نتحدث عن الفئة \p{} وعكس الفئة \P{} .

في Unicode ، يحتوي كل حرف على مجموعة من الخصائص. تتم الإشارة إلى هذه الخصائص في أقواس المجموعة \p{} . لذلك ، على سبيل المثال ، تحدد خاصية Script مجموعة اللغات التي ينتمي إليها الحرف ، ASCII خاصية ASCII ، والمنطقية ، true بالنسبة إلى أحرف ASCII ، وهكذا. على سبيل المثال ، سنكتشف ما إذا كانت بعض الأسطر تحتوي على أحرف ASCII فقط.

 console.log(r.test('abc')) //true console.log(r.test('ABC@')) //true console.log(r.test('ABC')) //false 

الخاصية ASCII_Hex_Digit true فقط للأحرف التي يمكن استخدامها لكتابة الأرقام السداسية عشرية.

 const r = /^\p{ASCII_Hex_Digit}+$/u console.log(r.test('0123456789ABCDEF')) //true console.log(r.test('H')) //false 

هناك العديد من الخصائص الأخرى المشابهة التي يتم استخدامها بنفس الطريقة الموضحة أعلاه. من بينها Uppercase ، Uppercase Lowercase ، White_Space ، Alphabetic ، Emoji .

على سبيل المثال ، إليك كيفية استخدام خاصية Script لتحديد الأبجدية المستخدمة في سلسلة. هنا نتحقق من السلسلة لاستخدام الأبجدية اليونانية.

 const r = /^\p{Script=Greek}+$/u console.log(r.test('ελληνικά')) //true console.log(r.test('hey')) //false 

يمكن الاطلاع على التفاصيل المتعلقة بهذه الخصائص هنا .

المجموعات المسماة


يمكن إعطاء مجموعات الأحرف الملتقطة في ES2018 أسماء. هنا هو كيف يبدو.

 const re = /(?<year>\d{4})-(?<month>\d{2})-(?<day>\d{2})/ const result = re.exec('2015-01-02') console.log(result) /* [ '2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: { year: '2015', month: '01', day: '02' } ] */ 

بدون استخدام المجموعات المسماة ، فإن نفس البيانات ستكون متاحة فقط كعناصر الصفيف.

 const re = /(\d{4})-(\d{2})-(\d{2})/ const result = re.exec('2015-01-02') console.log(result) /* [ '2015-01-02', '2015', '01', '02', index: 0, input: '2015-01-02', groups: undefined ] */ 

علم ريجكس


استخدام علامة s ينتج حرف . (نقطة) سوف ، من بين أمور أخرى ، تطابق شخصية السطر الجديد. بدون هذه العلامة ، تتطابق الفترة مع أي حرف باستثناء سطر جديد.

 console.log(/hi.welcome/.test('hi\nwelcome')) // false console.log(/hi.welcome/s.test('hi\nwelcome')) // true 

ملخص


باستخدام هذه المادة ، ننتهي من نشر ترجمات دليل JavaScript هذا . نأمل أن تساعد هذه المنشورات أولئك الذين لم يعملوا مع JavaScript قبل أن يتخذوا خطواتهم الأولى في البرمجة بهذه اللغة.

أعزائي القراء! إذا لم تكن قد كتبت بلغة JS من قبل واتقنت هذه اللغة في هذا الدليل ، فيرجى مشاركة انطباعاتك.

Source: https://habr.com/ru/post/ar431872/


All Articles