Funksiyalar bilan chuqur ishlash

Rest parametrlar va spread

Ko'p JavaScript funksiyalari ixtiyoriy sondagi argumentni qabul qila oladi โ€” masalan Math.max(1, 2, 3, 4). Bunday funksiyalarni yozish va massivlarni argumentlarga aylantirish uchun rest va spread sintaksisidan foydalanamiz. Ikkalasi ham uchta nuqta ... bilan yoziladi.

Rest parametrlar ...rest

Funksiya e'lon qilinganidan ortiqcha argument bilan chaqirilsa, JavaScript xatolik bermaydi โ€” ortiqcha argumentlarni oddiygina e'tiborsiz qoldiradi. Ammo biz ularning hammasini yig'ib olishimiz mumkin โ€” buning uchun oxirgi parametr oldiga ... qo'yamiz:

sum-all.js
// natija shu yerda chiqadi

...numbers โ€” bu "qolgan barcha argumentlarni numbers nomli massivga yig'" degani. So'zning o'zi ham shundan โ€” rest inglizcha "qolgani" degan ma'noni bildiradi.

Rest parametrdan oldin oddiy parametrlar ham bo'lishi mumkin. Ular birinchi argumentlarni oladi, qolgani esa restga tushadi:

rest-names.js
// natija shu yerda chiqadi
Rest parametr doim oxirgi bo'lishi shart. function f(arg1, ...rest, arg2) โ€” bu xatolik (SyntaxError), chunki restdan keyin boshqa parametr bo'lishi mumkin emas.

Eski usul: "arguments" obyekti

Eski JavaScript'da (rest parametrlar paydo bo'lishidan oldin) barcha argumentlarni olishning yagona yo'li maxsus arguments obyekti edi. U funksiya ichida avtomatik mavjud bo'ladi va indeks bo'yicha barcha argumentlarni saqlaydi:

arguments.js
// natija shu yerda chiqadi
arguments โ€” massivga o'xshaydi, lekin haqiqiy massiv emas. Unda .map(), .filter() kabi massiv metodlari yo'q. Shu sabab bugungi kunda deyarli har doim rest parametrlar afzal ko'riladi.
Yana bir muhim farq: strelka funksiyalarida (arrow functions) arguments obyekti umuman bo'lmaydi. Shu holatlarda ham rest parametrlar yagona to'g'ri yechim.

Spread sintaksisi ...spread

Rest parametr argumentlarni massivga yig'ardi. Spread esa buning aksi โ€” u massiv (yoki boshqa iteratsiyalanuvchi)ni alohida elementlarga yoyadi.

Klassik masala: Math.max alohida sonlarni kutadi, massivni emas. Massivdagi eng katta sonni topish uchun spread yordam beradi:

spread-max.js
// natija shu yerda chiqadi

Bir necha massivni yoki oddiy qiymatlarni birlashtirib ham chaqirish mumkin:

spread-multi.js
// natija shu yerda chiqadi

Spread bilan massivlarni yoyish va birlashtirish

Spreadni yangi massiv literali ichida ham ishlatish mumkin โ€” u massivni to'g'ridan-to'g'ri boshqa massivga "quyib" beradi:

spread-merge.js
// natija shu yerda chiqadi

Spread har qanday iteratsiyalanuvchi (iterable) bilan ishlaydi โ€” jumladan satr (string) bilan ham. Satrni belgilar massiviga aylantirish oson:

spread-string.js
// natija shu yerda chiqadi

Spread bilan nusxa olish

Spread massiv va obyektning sayoz nusxasini (shallow copy) olishning eng qulay usuli. Bu yerda muhim jihat bor โ€” massivni oddiygina boshqa o'zgaruvchiga tenglash nusxa yaratmaydi, faqat bir xil massivga ikkita nom beradi:

spread-copy.js
// natija shu yerda chiqadi

Xuddi shu usul obyektlar uchun ham ishlaydi:

spread-obj-copy.js
// natija shu yerda chiqadi
Bu sayoz (shallow) nusxa: agar obyekt ichida yana obyekt yoki massiv bo'lsa, ular nusxalanmaydi โ€” ikkala tomon bitta ichki obyektga ishora qiladi. Chuqur nusxa uchun boshqa usullar kerak (masalan structuredClone).
Qoidani eslab qoling: rest โ€” funksiya parametrlarida (argumentlarni yig'adi), spread โ€” funksiya chaqiruvida yoki massiv/obyekt literalida (yoyadi). Sintaksis bir xil ... bo'lsa-da, ular teskari ishlarni bajaradi.

Xulosa