وظائف النظام الأعلى في JavaScript: ما هي؟

نقدم لكم ترجمة لمقال Sukhjinder Arora المنشور على Bits and Pieces . اكتشف تحت القط حول وظائف الترتيب الأعلى في JavaScript وبعض الوظائف الأخرى المضمنة في هذه اللغة.


الصورة بواسطة NESA من قبل صناع Unsplash

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

بفضل القدرة على العمل مع وظائف عالية الترتيب ، تعد JavaScript مناسبة للبرمجة الوظيفية.

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

للحصول على صورة كاملة لوظائف الترتيب الأعلى ، تحتاج أولاً إلى فهم البرمجة الوظيفية ووظائف الدرجة الأولى .

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

ما هي البرمجة الوظيفية


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

تتم البرمجة الوظيفية بلغات مثل JavaScript و Haskell و Clojure و Scala و Erlang.

ما هي ميزات الدرجة الأولى


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

الدالات الخاصة بـ JavaScript بشكل خاص كائنات من نوع خاص (كائنات Function أو Function ). على سبيل المثال:

 function greeting() { console.log('Hello World'); } // Invoking the function greeting(); // prints 'Hello World' 

لإظهار أن الوظائف في JavaScript هي كائنات ، يمكننا القيام بشيء مثل هذا:

 // We can add properties to functions like we do with objects greeting.lang = 'English'; // Prints 'English' console.log(greeting.lang); 

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

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

تعيين وظائف للمتغيرات


تسمح لك JavaScript بتعيين الوظائف للمتغيرات. على سبيل المثال:

 const square = function(x) { return x * x; } // prints 25 square(5); 

يمكن أيضًا نقلها. على سبيل المثال:

 const foo = square; // prints 36 foo(6); 

تمرير الوظائف كوسيطة


يمكننا تمرير الدوال كحجج للدوال الأخرى. على سبيل المثال:

 function formalGreeting() { console.log("How are you?"); } function casualGreeting() { console.log("What's up?"); } function greet(type, greetFormal, greetCasual) { if(type === 'formal') { greetFormal(); } else if(type === 'casual') { greetCasual(); } } // prints 'What's up?' greet('casual', formalGreeting, casualGreeting); 

الآن ، بعد أن عرفنا ما هي وظائف الدرجة الأولى ، دعنا ننتقل إلى وظائف الترتيب الأعلى في JavaScript.

وظائف ترتيب أعلى


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

من أمثلة الدالات عالية الترتيب المضمنة بالفعل في اللغة Array.prototype.map و Array.prototype.filter و Array.prototype.reduce .

وظائف النظام الأعلى في العمل


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

Array.prototype.map
ينشئ أسلوب map() صفيفًا جديدًا نتيجة استدعاء الوظيفة الممررة لكل عنصر من عناصر الصفيف الأولي. تأخذ طريقة map() كل قيمة من وظائف رد الاتصال وتنشئ مصفوفة جديدة باستخدام هذه القيم.

تأخذ وظيفة رد الاتصال التي تم تمريرها إلى طريقة map() ثلاث وسيطات: element index array .

تأمل هذا مع بعض الأمثلة.

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

بدون وظيفة ترتيب أعلى:

 const arr1 = [1, 2, 3]; const arr2 = []; for(let i = 0; i < arr1.length; i++) { arr2.push(arr1[i] * 2); } // prints [ 2, 4, 6 ] console.log(arr2); 

استخدام وظيفة map الترتيب الأعلى:

 const arr1 = [1, 2, 3]; const arr2 = arr1.map(function(item) { return item * 2; }); console.log(arr2); 

يمكن جعل الكود أقصر باستخدام وظيفة السهم.

 const arr1 = [1, 2, 3]; const arr2 = arr1.map(item => item * 2); console.log(arr2); 

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

بدون وظيفة ترتيب أعلى:

 const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = []; for(let i = 0; i < birthYear.length; i++) { let age = 2018 - birthYear[i]; ages.push(age); } // prints [ 43, 21, 16, 23, 33 ] console.log(ages); 

استخدام وظيفة map الترتيب الأعلى:

 const birthYear = [1975, 1997, 2002, 1995, 1985]; const ages = birthYear.map(year => 2018 - year); // prints [ 43, 21, 16, 23, 33 ] console.log(ages); 

Array.prototype.filter
تنشئ طريقة filter() صفيفًا جديدًا اجتازت جميع العناصر الاختبار المحدد في الدالة التي تم تمريرها. تأخذ وظيفة رد الاتصال التي تم تمريرها إلى filter() ثلاث وسيطات: element index array .

تأمل هذا مع بعض الأمثلة.

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

بدون وظيفة ترتيب أعلى:

 const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = []; for(let i = 0; i < persons.length; i++) { if(persons[i].age >= 18) { fullAge.push(persons[i]); } } console.log(fullAge); 

باستخدام وظيفة filter الدرجة الأعلى:

 const persons = [ { name: 'Peter', age: 16 }, { name: 'Mark', age: 18 }, { name: 'John', age: 27 }, { name: 'Jane', age: 14 }, { name: 'Tony', age: 24}, ]; const fullAge = persons.filter(person => person.age >= 18); console.log(fullAge); 

Array.prototype.reduce
يطبق أسلوب التصغير دالة على كل قيمة للصفيف ، ويقللها إلى قيمة واحدة. تأخذ طريقة التصغير وسيطتين:
  1. وظيفة رد الاتصال المراد معالجتها ؛
  2. معلمة initialValue اختيارية (الوسيطة الأولى في استدعاء الوظيفة الأولى).

تأخذ وظيفة رد الاتصال أربع وسائط: accumulator ، currentValue ، currentIndex ، sourceArray .

إذا تم تمرير المعلمة initialValue ، فستكون وسيطة accumulator مساوية initialValue ، currentValue وسيطة currentValue هي العنصر الأول للصفيف.

إذا لم يتم تمرير المعلمة initialValue ، فستكون وسيطة accumulator مساوية للعنصر الأول من الصفيف ، وسيتم أخذ العنصر الثاني للصفيف كوسيطة currentValue .

المثال رقم 1
افترض أننا بحاجة إلى العثور على مجموع الأرقام في صفيف.

يؤدي استخدام وظيفة ترتيب أعلى إلى reduce :

 const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }); // prints 25 console.log(sum); 

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

بالإضافة إلى ذلك ، يمكننا تمرير هذه الوظيفة القيمة الأولية:

 const arr = [5, 7, 1, 8, 4]; const sum = arr.reduce(function(accumulator, currentValue) { return accumulator + currentValue; }, 10); // prints 35 console.log(sum); 

بدون وظيفة ترتيب أعلى:

 const arr = [5, 7, 1, 8, 4]; let sum = 0; for(let i = 0; i < arr.length; i++) { sum = sum + arr[i]; } // prints 25 console.log(sum); 

كما ترون ، بمساعدة وظيفة ترتيب أعلى ، يمكن جعل الرمز أكثر دقة وأقصر وأكثر سعة.

قم بإنشاء وظيفة الترتيب الأعلى الخاصة بك


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

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

لنفترض أن لدينا مصفوفة من السلاسل ، ونريد منه إنشاء مصفوفة من التكاملات يمثل فيها كل عنصر طول السلسلة من الصفيف الأولي.

 const strArray = ['JavaScript', 'Python', 'PHP', 'Java', 'C']; function mapForEach(arr, fn) { const newArray = []; for(let i = 0; i < arr.length; i++) { newArray.push( fn(arr[i]) ); } return newArray; } const lenArray = mapForEach(strArray, function(item) { return item.length; }); // prints [ 10, 6, 3, 4, 1 ] console.log(lenArray); 

في المثال أعلاه ، أنشأنا دالة mapForEach ذات الترتيب mapForEach ، والتي تأخذ مصفوفة ووظيفة رد اتصال fn mapForEach . يتم تطبيق هذه الوظيفة بشكل دوري على كل عنصر من عناصر الصفيف وتستدعي وظيفة رد الاتصال fn كجزء من newArray.push دالة newArray.push في كل تكرار.

تأخذ وظيفة رد الاتصال fn العنصر الحالي للصفيف الأولي وترجع قيمة طول هذا العنصر ، المخزنة داخل newArray الجديد newArray . بعد اكتمال التكرار ، newArray إرجاع صفيف newArray كنتيجة lenArray صفيف lenArray .

الخلاصة


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

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

هذا ، في الواقع ، كل شيء. إذا وجدت هذه المقالة مفيدة ، يمكنك أيضًا متابعتي على Medium وعلى Twitter . لا تتردد في التعليق إذا كان لديك أي أسئلة! سأكون سعيدا للمساعدة. :)

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


All Articles