وظائف سهم JavaScript: سبب الحاجة إليها ، وكيفية التعامل معها ، ومتى يتم استخدامها ، ومتى لا

أحد أهم ابتكارات JavaScript الحديثة هو ظهور وظائف الأسهم ، والتي تسمى أحيانًا وظائف "الدهون". عند الإعلان عن مثل هذه الوظائف ، يستخدمون مجموعة خاصة من الأحرف - => .

وظائف السهم لها ميزتان رئيسيتان على الوظائف التقليدية. الأول هو بناء جملة مريح ومضغوط للغاية. والثاني هو أن نهج العمل مع this في وظائف الأسهم يبدو أكثر بديهية من الوظائف العادية.

الصورة

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

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

ستركز المادة التي ننشر ترجمتها اليوم على كيفية عمل وظائف السهم. سننظر هنا في المواقف التي يمكن لاستخدامها فيها تحسين الشفرة ، والمواقف التي لا يجب استخدامها فيها.

وظائف سهم الميزات في جافا سكريبت


وظائف السهم في JavaScript هي شيء يشبه دالات لامدا في بايثون وكتل في روبي.

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

لنتحدث عن هذا بمزيد من التفصيل.

functions وظائف سهم النحو


يتم بناء وظائف السهم وفقًا لمخطط واحد ، بينما يمكن تبسيط هيكل الوظائف ، في حالات خاصة. تبدو البنية الأساسية لوظيفة السهم كما يلي:

 (argument1, argument2, ... argumentN) => { //   } 

قائمة وسيطات الدالة موجودة بين قوسين ، متبوعًا بسهم مكون من = و > الأحرف ، ثم يأتي نص الدالة بين أقواس.

هذا مشابه جدًا لكيفية عمل الدالات العادية ، الاختلافات الرئيسية هي حذف الكلمة الرئيسية function هنا وإضافة سهم بعد قائمة الوسيطات.

ومع ذلك ، في حالات معينة ، يمكن الإعلان عن وظائف الأسهم البسيطة باستخدام تركيبات أكثر تعقيدًا.

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

 const add = (a, b) => a + b; 

فيما يلي متغير آخر للرمز المختصر للدالة ، يستخدم عندما يكون للدالة وسيطة واحدة فقط.

 const getFirst = array => array[0]; 

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

objectsإعادة الكائنات ووظائف سهم السجل القصير


عند العمل مع وظائف الأسهم ، يتم أيضًا استخدام بعض تراكيب بناء الجملة الأكثر تعقيدًا ، وهي مفيدة لتكون على دراية بها.

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

 (name, description) => {name: name, description: description}; 

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

للإشارة إلى النظام أننا نعني الكائن الحرفي ، نحتاج إلى وضعه بين قوسين:

 (name, description) => ({name: name, description: description}); 

functions وظائف السهم وسياق تنفيذها


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

في الممارسة العملية ، هذا يعني أنهم يرثون هذه الكيانات arguments من الوظيفة الأصلية.

على سبيل المثال ، قارن بين الوظيفتين المقدمتين في الكود التالي. واحد منهم عادي ، والثاني هو السهم.

 const test = { name: 'test object', createAnonFunction: function() {   return function() {     console.log(this.name);     console.log(arguments);   }; }, createArrowFunction: function() {   return () => {     console.log(this.name);     console.log(arguments);   }; } }; 

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

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

 > const anon = test.createAnonFunction('hello', 'world'); > const arrow = test.createArrowFunction('hello', 'world'); > anon(); undefined {} > arrow(); test object { '0': 'hello', '1': 'world' } 

الوظيفة المجهولة لها سياقها الخاص ، لذلك عندما يتم استدعاؤها ، عند استدعاء test.name ، لن يتم test.name قيمة خاصية name الكائن ، وعند استدعاء arguments ، لن يتم عرض قائمة الوسائط إلى الدالة التي تم استخدامها لإنشاء وإرجاع الوظيفة قيد التحقيق.

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

تعمل المواقف التي تعمل فيها وظائف الأسهم على تحسين الرمز


lists معالجة قوائم القيم


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

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

 const words = ['hello', 'WORLD', 'Whatever']; const downcasedWords = words.map(word => word.toLowerCase()); 

فيما يلي مثال شائع للغاية للاستخدام المماثل لوظائف الأسهم ، والتي تتكون من العمل مع خصائص الكائنات:

 const names = objects.map(object => object.name); 

وبالمثل ، إذا forEach حلقات forEach المستندة إلى forEach بدلاً من التقليدية للحلقات ، فإن وظائف الأسهم this تستخدم this الكيان الأصلي ، مما يجعل استخدامها بديهيًا:

 this.examples.forEach(example => { this.runExample(example); }); 

▍ الوعود وسلاسل الوعد


هناك موقف آخر حيث تسمح لك وظائف الأسهم بكتابة كود أنظف وأكثر قابلية للفهم يتمثل في بنيات برامج غير متزامنة.

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

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

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

 this.doSomethingAsync().then((result) => { this.storeResult(result); }); 

▍ تحويل الكائن


حالة استخدام شائعة أخرى لوظائف الأسهم هي تغليف تحويلات الكائنات.

على سبيل المثال ، في Vue.js ، هناك نمط شائع لتضمين أجزاء تخزين Vuex مباشرة في مكون Vue باستخدام mapState .

تتضمن هذه العملية إعلانات عن مجموعة من "المحولات" التي تحدد بالضبط ما هو مطلوب لمكون معين من الحالة الكاملة الأولية.

هذه التحولات البسيطة هي المكان المثالي لاستخدام وظائف الأسهم. على سبيل المثال:

 export default { computed: {   ...mapState({     results: state => state.results,     users: state => state.users,   }); } } 

الحالات التي يجب عدم استخدام وظائف الأسهم فيها


▍ طرق الكائنات


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

الحالة الأولى هي استخدام وظائف الأسهم كطرق للكائن. سياق التنفيذ this الخاصة بالوظائف التقليدية مهمان هنا.

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

 class Counter { counter = 0; handleClick = () => {   this.counter++; } } 

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

ومع ذلك ، فإن هذا النهج لديه الكثير من السلبيات التي خصصت لها هذه المواد .

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

في مثل هذه الحالات ، بدلاً من دالات الأسهم ، استخدم الدالات العادية ، وإذا لزم الأمر ، اربطها بمثيل للكائن في المُنشئ:

 class Counter { counter = 0; handleClick() {   this.counter++; } constructor() {   this.handleClick = this.handleClick.bind(this); } } 

سلاسل المكالمات الطويلة


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

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

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

 {anonymous}() {anonymous}() {anonymous}() {anonymous}() {anonymous}() 

▍ وظائف ذات سياق ديناميكي


آخر المواقف التي نناقشها والتي يمكن أن تصبح فيها وظائف الأسهم مصدرًا للمشكلات هي استخدامها حيث تحتاج إلى ديناميكية this الربط.

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

فيما يلي بعض الأشياء التي يجب وضعها في الاعتبار عند التفكير في استخدام وظائف الأسهم:

  • يتم استدعاء معالجات الأحداث باستخدام this المنضم إلى سمة حدث currentTarget .
  • إذا كنت لا تزال تستخدم jQuery ، ففكر في أن معظم طرق jQuery تربط this بعنصر DOM المحدد.
  • إذا كنت تستخدم Vue.js ، فإن الطرق والوظائف المحسوبة عادة ما تربط this بمكون Vue.

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

الملخص


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

أعزائي القراء! هل واجهت مواقف يؤدي فيها استخدام وظائف الأسهم إلى أخطاء أو إزعاج أو سلوك غير متوقع للبرامج؟

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


All Articles