6 ميزات جافا سكريبت يجب أن تعرفها

نشرت: 2020-09-24

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

سأعرض لكم اليوم ست ميزات رائعة من JavaScript حقًا. عوامل التشغيل ، النطاق المتغير ، الوعود ، الوظائف غير المتزامنة ... هل أنت مستعد لتعلمها جميعًا؟

# 1 تسلسل اختياري في JavaScript مع المشغل ?.

يسمح عامل التسلسل الاختياري بالوصول المبسط إلى سمات الكائن عندما يكون هناك احتمال أن يكون العنصر غير undefined أو null . على سبيل المثال ، افترض أن لديك كائنًا مثل ما يلي:

 const toni = { name: 'Antonio', details: { age: 35, }, };

للوصول إلى age toni ، يمكنك أولاً الوصول إلى سمة details ثم age :

 function getAge( person ) { return person.details.age; }

المشكلة التي لدينا في الوظيفة السابقة ، وأنا متأكد من أنها ليست جديدة بالنسبة لك ، هي أن الخصائص التي نتوقع أن يمتلكها person ليست موجودة دائمًا. هذا إذا كان أي person أو شخص person.details غير undefined ، ستؤدي الوظيفة المذكورة أعلاه إلى ظهور خطأ في النوع:

 getAge( toni ); // 35 getAge( {} ); // Uncaught TypeError: person.details is undefined

عادة نتغلب على هذه المشكلة بإضافة بعض الحراس الآمنين:

 function getAge( person ) { if ( ! person ) { return; } if ( ! person.details ) { return; } return person.details.age; } getAge( toni ); // 35 getAge( {} ); // undefined

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

 function getAge( person ) { return person?.details?.age; } getAge( toni ); // 35 getAge( {} ); // undefined

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

# 2 عامل ائتلاف لاغي ( ?? )

في JavaScript ، من السهل جدًا تعيين قيمة افتراضية لمتغير باستخدام هذا العامل: || ، الصحيح؟ خاطئ - ظلم - يظلم! لقد فعلنا جميعًا هذا ، ولكن يمكن أن يؤدي إلى آثار جانبية غير متوقعة إذا لم تكن حريصًا ...

على سبيل المثال ، لنفترض أن لدينا محددًا في متجر Redux يسمح لنا باسترداد القيمة التي حددها المستخدم. إذا لم يحدد المستخدم قيمة بعد (أي أن القيمة غير undefined ) ، فإننا نعيد القيمة الافتراضية باستخدام || :

 function getValue( state ) { return state.value || 5; }

الآن ، دعنا نرى بعض الأمثلة لما سنحصل عليه مع الوظيفة السابقة بعد أن قام المستخدم بتعيين قيمة أو أخرى:

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 5

عذرًا! كل شيء سار بشكل جيد حتى وصلنا إلى الحالة الأخيرة! على ما يبدو ، إذا قام المستخدم بتعيين القيمة على 0 ، تصبح نتيجة الوظيفة 5 . لماذا ا؟ حسنًا ، الأساس المنطقي مطيع جدًا: x||y تعيد y إذا ، وفقط إذا كانت x قيمة "خاطئة". هذا عادة ما يعمل بشكل جيد ، حيث أن القيمة undefined هي قيمة خاطئة. ولكن ذلك هو false أو 0 ، على سبيل المثال.

في الواقع ، أردنا فقط تعيين قيمة default في حالة عدم وجود أي قيمة. لذلك يمكننا إضافة حارس آمن للتحقق مما إذا كانت هناك قيمة أم لا:

 function getValue( state ) { if ( undefined === state.value ) return 5; return state.value; }

ويمكننا حتى كتابته باستخدام عامل التشغيل الثلاثي إذا شعرنا بالخيال:

 function getValue( state ) { return undefined === state.value ? 5 : state.value; }

ولكن ، مرة أخرى ، يؤدي كلا الحلين إلى تعقيد الشفرة دون داع. لتعيين قيمة افتراضية لمتغير ، يجب أن نستخدم عامل الاندماج الصفري ?? ، والتي تُرجع الجزء الأيمن إذا ، وفقط إذا كان الجزء الأيسر null أو undefined :

 function getValue( state ) { return state.value ?? 5; }

و مفاجأة مفاجأة! النتيجة هي بالضبط ما أردناه:

 // No setValue( x )... getValue(); // 5 setValue( 2 ); getValue(); // 2 setValue( 1 ); getValue(); // 1 setValue( 0 ); getValue(); // 0

أوه ، وبالمناسبة ، يمكنك استخدام هذا العامل مع مهمة. على سبيل المثال ، هذا:

 value = value ?? 5;

يعادل هذا:

 value ??= 5;

# 3 الوعود والوظائف غير المتزامنة

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

في إصدارات JavaScript والمكتبات الأقدم (على سبيل المثال ، jQuery) اعتدنا تنفيذ ذلك مع عمليات الاسترجاعات. كانت الفكرة بسيطة للغاية: إلى جانب الطلب نفسه ، حدد الوظيفة (رد الاتصال) التي يجب استدعاؤها بمجرد توفر الاستجابة. بهذه الطريقة ، عند اكتمال العملية غير المتزامنة (أي استرداد البيانات من الخادم) ، ستستدعي المكتبة الوظيفة وسيستأنف منطقنا:

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/users/1', success: ( user ) => { console.log( user ); }, } );

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

 jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/1', success: ( user1 ) => { jQuery.ajax( { url: 'https://server.com/wp-json/wp/v2/users/2', success: ( user2 ) => { console.log( user1, user2 ); }, } ); }, } );

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

على سبيل المثال ، إذا أردنا إعادة كتابة مقتطفنا الأول باستخدام الوعود ، فسيبدو كما يلي:

 const promise = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); promise.then( ( user ) => console.log( user ) );

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

ربما تفكر الآن أن هذا ليس بهذه الصعوبة مما كان لدينا من قبل ، أليس كذلك؟ بعد كل شيء ، ما زلنا نستخدم عمليات الاسترجاعات ... ولكن يمكنك أن ترى مدى فائدة ذلك بمجرد أن نبدأ في دمج طلبات متعددة:

 const promise1 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/1', } ); const promise2 = wp.apiFetch( { url: 'https://server.com/wp-json/wp/v2/users/2', } ); Promise.all( [ promise1, promise2 ] ).then( ( [ user1, user2 ] ) => console.log( user1, user2 ); );

باستخدام الوعود ، تمكنا من إطلاق طلبين متوازيين لاسترداد المستخدمين 1 و 2 واستخدام Promise.all لانتظار حل الوعدتين. لا يوجد كود سباغيتي مع عمليات رد نداء متداخلة.

حسنًا ، إن الشيء العظيم في الوعود على وشك أن يأتي. يمكننا استخدام بعض السكر النحوي للعمل مع وعود JavaScript وكتابة تعليمات برمجية غير متزامنة تبدو متزامنة بشكل جيد. كل ما عليك فعله هو تحديد وظيفة غير متزامنة باستخدام الكلمة الأساسية غير المتزامنة وتصبح الأمور فجأة أسهل بكثير:

 async function logTwoUsers( id1, id2 ) { const user1 = await wp.apiFetch( { url: '…' + id1 } ); const user2 = await wp.apiFetch( { url: '…' + id2 } ); console.log( user1, user2 ); }

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

 async function getNumberFive() { return 5; } const p = getNumberFive(); // a promise p.then( console.log ); // prints "5"

# 4 النطاق المتغير عند استخدام let و const

كما تعلم بالفعل ، يمكنك الآن إعلان المتغيرات باستخدام الكلمتين الأساسيتين let و const . الأول يحدد متغيرًا والثاني يحدد ثابتًا:

 let x = 1; console.log( x ); // 1 x = 2; console.log( x ); // 2 const y = 1; console.log( y ); // 1 y = 2; // Uncaught TypeError: invalid assignment to const 'y' console.log( y ); // 1

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

 function fn() { if ( true ) { var x = 1; let y = 2; const z = 3; }//end if console.log( x ); // 1 console.log( y ); // Uncaught ReferenceError: y is not defined console.log( z ); // Uncaught ReferenceError: z is not defined }

# 5 تحويل البيانات عند استخدام JSON.parse

تحلل الدالة JSON.parse سلسلة JSON وتقوم ببناء كائن JavaScript. علي سبيل المثال:

 const x = JSON.parse( '{"x":1,"a":[1,2,3]}' ); // Object { x: 1, a: [ 1, 2, 3 ] }

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

 const json = '{"name":"David","birthday":"1985-12-01T10:00:00.000Z"}';

إذا استخدمنا JSON.parse كما هو ، فسيُنشئ كائنًا بخاصيتين من سمات السلسلة: name birthday . ولكن إذا قدمنا ​​دالة إحياء إلى reviver ، فيمكننا التأكد من أن تاريخ birthday يتم تحليله JSON.parse Date

 const user = JSON.parse( json, ( key, value ) => 'birthday' === key ? new Date( value ) : value )

# 6 فاصل رقمي في التعليمات البرمجية المصدر باستخدام الحرف السفلية ( _ )

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

 10000000000 2189719.25

إذا تمكنا فقط من استخدام فاصل الآلاف ، فسيكون من الأسهل تفسيره! وهذا بالضبط ما يمكننا فعله باستخدام الشرطة السفلية _ :

 10_000_000_000 2_189_719.25

ملخص

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

صورة مميزة بواسطة Sam Dan Truong على Unsplash.