تدعم العديد من وظائف JavaScript المضمنة عددًا عشوائيًا من الوسائط.
على سبيل المثال:
Math.max(arg1, arg2, ..., argN)
- يُرجع أكبر الوسائط.
Object.assign(dest, src1, ..., srcN)
– ينسخ الخصائص من src1..N
إلى dest
.
…وهلم جرا.
وفي هذا الفصل سوف نتعلم كيفية القيام بالشيء نفسه. وأيضًا كيفية تمرير المصفوفات إلى وظائف مثل المعلمات.
...
يمكن استدعاء الدالة بأي عدد من الوسائط، بغض النظر عن كيفية تعريفها.
مثل هنا:
مجموع الدالة (أ، ب) { العودة أ + ب؛ } تنبيه(مجموع(1, 2, 3, 4, 5));
لن يكون هناك خطأ بسبب الحجج "المفرطة". لكن بالطبع في النتيجة سيتم احتساب الأولين فقط، وبالتالي فإن النتيجة في الكود أعلاه هي 3
.
يمكن تضمين باقي المعلمات في تعريف الدالة باستخدام ثلاث نقاط ...
متبوعة باسم المصفوفة التي ستحتوي عليها. تعني النقاط حرفيًا "جمع المعلمات المتبقية في مصفوفة".
على سبيل المثال، لتجميع كافة الوسائط في args
المصفوفة:
function sumAll(...args) { // args هو اسم المصفوفة دع المبلغ = 0؛ for (let arg of the args) sum += arg; مبلغ الإرجاع؛ } تنبيه(مجموع(1)); // 1 تنبيه(مجموع(1, 2)); // 3 تنبيه( sumAll(1, 2, 3) ); // 6
يمكننا اختيار الحصول على المعلمات الأولى كمتغيرات، وجمع الباقي فقط.
هنا تدخل الوسيطتان الأوليان في المتغيرات وينتقل الباقي إلى مصفوفة titles
:
وظيفة showName(firstName, lastName, ...titles) { تنبيه (الاسم الأول + ' ' + الاسم الأخير ); // يوليوس قيصر // يذهب الباقي إلى مصفوفة العناوين // أي العناوين = ["القنصل"، "الإمبراطور"] تنبيه(العناوين[0]); // القنصل تنبيه (العناوين[1])؛ // الإمبراطور تنبيه (العناوين. الطول)؛ // 2 } showName("يوليوس", "قيصر", "القنصل", "الإمبراطور");
يجب أن تكون المعلمات المتبقية في النهاية
تجمع المعلمات المتبقية جميع الوسائط المتبقية، لذا فإن ما يلي غير منطقي ويسبب خطأ:
الوظيفة f(arg1, ...rest, arg2) {// arg2 بعد ...rest؟! // خطأ }
...rest
يجب أن يكون دائمًا الأخير.
يوجد أيضًا كائن خاص يشبه arguments
يسمى الوسائط، والذي يحتوي على جميع الوسائط حسب فهرسها.
على سبيل المثال:
اسم العرض الدالة () { تنبيه (الحجج. الطول)؛ تنبيه(الحجج[0]); تنبيه(الحجج[1]); // إنه قابل للتكرار // for(اسمح بوسيطات الوسائط) تنبيه(arg); } // يظهر: 2، يوليوس، قيصر showName("يوليوس", "قيصر"); // يظهر: 1، إيليا، غير محدد (بدون وسيطة ثانية) showName("ايليا");
في العصور القديمة، لم تكن معلمات الراحة موجودة في اللغة، وكان استخدام arguments
هو الطريقة الوحيدة للحصول على جميع وسائط الوظيفة. وما زال يعمل، يمكننا العثور عليه في الكود القديم.
لكن الجانب السلبي هو أنه على الرغم من أن arguments
تشبه المصفوفة وقابلة للتكرار، إلا أنها ليست مصفوفة. إنه لا يدعم أساليب المصفوفة، لذا لا يمكننا استدعاء arguments.map(...)
على سبيل المثال.
كما أنه يحتوي دائمًا على كافة الوسائط. لا يمكننا التقاطها جزئيًا، كما فعلنا مع معلمات الراحة.
لذلك عندما نحتاج إلى هذه الميزات، فإننا نفضل معلمات الراحة.
وظائف السهم لا تحتوي على "arguments"
إذا وصلنا إلى كائن arguments
من دالة سهمية، فسوف يأخذها من الوظيفة "العادية" الخارجية.
هنا مثال:
الدالة و() { Let showArg = () => تنبيه(arguments[0]); showArg(); } و(1); // 1
كما نتذكر، وظائف السهم ليس لها this
. الآن نعلم أنهم لا يملكون كائن arguments
الخاصة أيضًا.
لقد رأينا للتو كيفية الحصول على مصفوفة من قائمة المعلمات.
لكن في بعض الأحيان نحتاج إلى القيام بالعكس تمامًا.
على سبيل المثال، هناك دالة مضمنة Math.max تقوم بإرجاع أكبر رقم من القائمة:
تنبيه( Math.max(3, 5, 1) ); // 5
لنفترض الآن أن لدينا مصفوفة [3, 5, 1]
. كيف نسمي Math.max
به؟
لن ينجح تمريرها "كما هي"، لأن Math.max
تتوقع قائمة من الوسائط الرقمية، وليس مصفوفة واحدة:
دع arr = [3, 5, 1]; تنبيه( Math.max(arr)); // نان
وبالتأكيد لا يمكننا إدراج العناصر يدويًا في الكود Math.max(arr[0], arr[1], arr[2])
، لأننا قد لا نكون متأكدين من عددها. أثناء تنفيذ البرنامج النصي الخاص بنا، قد يكون هناك الكثير، أو قد لا يكون هناك أي شيء. وهذا من شأنه أن يصبح قبيحًا.
نشر بناء الجملة للإنقاذ! يبدو مشابهًا لمعلمات الراحة، ويستخدم أيضًا ...
، ولكنه يفعل العكس تمامًا.
عند استخدام ...arr
في استدعاء الدالة، فإنه "يوسع" arr
القابل للتكرار إلى قائمة الوسائط.
بالنسبة إلى Math.max
:
دع arr = [3, 5, 1]; تنبيه( Math.max(...arr) ); // 5 (الانتشار يحول المصفوفة إلى قائمة من الوسائط)
يمكننا أيضًا تمرير عدة تكرارات بهذه الطريقة:
دع arr1 = [1, -2, 3, 4]; دع arr2 = [8, 3, -8, 1]; تنبيه( Math.max(...arr1, ...arr2) ); // 8
يمكننا أيضًا دمج صيغة الانتشار مع القيم العادية:
دع arr1 = [1, -2, 3, 4]; دع arr2 = [8, 3, -8, 1]; تنبيه( Math.max(1, ...arr1, 2, ...arr2, 25) ); // 25
أيضًا، يمكن استخدام صيغة الانتشار لدمج المصفوفات:
دع arr = [3, 5, 1]; دع arr2 = [8, 9, 15]; Let merged = [0, ...arr, 2, ...arr2]; تنبيه (دمج)؛ // 0,3,5,1,2,8,9,15 (0، ثم arr، ثم 2، ثم arr2)
في الأمثلة أعلاه، استخدمنا مصفوفة لتوضيح صيغة الانتشار، ولكن أي كائن قابل للتكرار سيفي بالغرض.
على سبيل المثال، نستخدم هنا صيغة الانتشار لتحويل السلسلة إلى مجموعة من الأحرف:
دع str = "مرحبا"; تنبيه([... شارع])؛ // مرحبًا
يستخدم بناء الجملة الانتشار داخليًا التكرارات لجمع العناصر، بنفس الطريقة التي يستخدمها for..of
.
لذا، بالنسبة للسلسلة، for..of
تُرجع الأحرف و ...str
تصبح "H","e","l","l","o"
. يتم تمرير قائمة الأحرف إلى مُهيئ الصفيف [...str]
.
يمكننا أيضًا استخدام Array.from
لهذه المهمة تحديدًا، لأنه يحول كائنًا قابلاً للتكرار (مثل سلسلة نصية) إلى مصفوفة:
دع str = "مرحبا"; // Array.from يحول العنصر القابل للتكرار إلى مصفوفة تنبيه(Array.from(str)); // مرحبًا
والنتيجة هي نفسها [...str]
.
ولكن هناك فرق دقيق بين Array.from(obj)
و [...obj]
:
يعمل Array.from
على كل من المصفوفات المشابهة والقابلة للتكرار.
صيغة الانتشار تعمل فقط مع العناصر القابلة للتكرار.
لذلك، بالنسبة لمهمة تحويل شيء ما إلى مصفوفة، يميل Array.from
إلى أن يكون أكثر عالمية.
هل تتذكر عندما تحدثنا عن Object.assign()
في الماضي؟
من الممكن أن تفعل الشيء نفسه مع بناء جملة الانتشار.
دع arr = [1, 2, 3]; دع arrCopy = [...arr]; // قم بتوزيع المصفوفة في قائمة المعلمات // ثم ضع النتيجة في مصفوفة جديدة // هل تحتوي المصفوفات على نفس المحتويات؟ تنبيه(JSON.stringify(arr) === JSON.stringify(arrCopy)); // حقيقي // هل المصفوفات متساوية؟ تنبيه (arr === arrCopy)؛ // خطأ (ليس نفس المرجع) // تعديل المصفوفة الأولية لا يؤدي إلى تعديل النسخة: arr.push(4); تنبيه(arr); // 1، 2، 3، 4 تنبيه(arrCopy); // 1، 2، 3
لاحظ أنه من الممكن القيام بنفس الشيء لإنشاء نسخة من كائن ما:
Let obj = { a: 1, b: 2, c: 3 }; Let objCopy = { ...obj }; // قم بتوزيع الكائن في قائمة المعلمات // ثم قم بإرجاع النتيجة في كائن جديد // هل تحتوي الكائنات على نفس المحتويات؟ تنبيه(JSON.stringify(obj) === JSON.stringify(objCopy)); // حقيقي // هل الكائنات متساوية؟ تنبيه (obj === objCopy)؛ // خطأ (ليس نفس المرجع) // تعديل الكائن الأولي لا يؤدي إلى تعديل النسخة: obj.d = 4; تنبيه (JSON.stringify (obj))؛ // {"أ":1،"ب":2،"ج":3،"د":4} تنبيه (JSON.stringify (objCopy))؛ // {"أ":1،"ب":2،"ج":3}
هذه الطريقة لنسخ كائن أقصر بكثير من let objCopy = Object.assign({}, obj)
أو بالنسبة للمصفوفة، let arrCopy = Object.assign([], arr)
لذلك نفضل استخدامها كلما استطعنا.
عندما نرى "..."
في الكود، فهي إما معلمات بقية أو بناء جملة الانتشار.
هناك طريقة سهلة للتمييز بينهما:
عندما يكون ...
في نهاية معلمات الوظيفة، فهو "معلمات بقية" ويجمع بقية قائمة الوسائط في مصفوفة.
عندما يحدث ...
في استدعاء دالة أو ما شابه، يطلق عليه "بناء جملة الانتشار" ويقوم بتوسيع المصفوفة إلى قائمة.
استخدام الأنماط:
تُستخدم معلمات الراحة لإنشاء وظائف تقبل أي عدد من الوسائط.
يتم استخدام بناء جملة الانتشار لتمرير مصفوفة إلى الوظائف التي تتطلب عادةً قائمة من العديد من الوسائط.
يساعدان معًا على التنقل بين قائمة ومجموعة من المعلمات بسهولة.
جميع وسيطات استدعاء الوظيفة متاحة أيضًا في arguments
"النمط القديم": كائن قابل للتكرار يشبه المصفوفة.