Spread va Rest operatori
Muammodan boshlaylik
Ikkita massivni birlashtirish kerak. Yoki funksiya nechta argument olishini oldindan bilmaysiz. Yoki ob'ektni nusxalash kerak, lekin Object.assign({}, ...) yozish uzoq tuyuladi.
Bularning barchasi uchun JavaScript da bitta operator bor — uch nuqta .... Lekin u ikki xil joyda ikki xil ma'no anglatadi: spread va rest.
Spread operatori — yoyish
Spread ... — massiv yoki ob'ektni "yoyib" yuboradi. Idishdagi narsalarni stolga to'kib tashlagan kabi — ichidagi elementlar alohida-alohida chiqadi.
Massivda spread
const mevalar = ["olma", "nok", "uzum"];
console.log(mevalar); // ["olma", "nok", "uzum"] — massiv
console.log(...mevalar); // "olma" "nok" "uzum" — alohida qiymatlar
Massivlarni birlashtirish:
const sabzavotlar = ["sabzi", "piyoz"];
const mevalar = ["olma", "nok"];
// Eski usul
const hammasi1 = sabzavotlar.concat(mevalar);
// Spread bilan
const hammasi2 = [...sabzavotlar, ...mevalar];
console.log(hammasi2); // ["sabzi", "piyoz", "olma", "nok"]
O'rtaga element qo'shish ham oson:
const boshida = [0, 1, 2];
const oxirida = [6, 7, 8];
const toʻliq = [...boshida, 3, 4, 5, ...oxirida];
console.log(toʻliq); // [0, 1, 2, 3, 4, 5, 6, 7, 8]
Massivni nusxalash:
const asl = [1, 2, 3];
// Xato usul — bir xil massivga havola
const nusxa1 = asl;
nusxa1.push(4);
console.log(asl); // [1, 2, 3, 4] — asl ham o'zgardi!
// To'g'ri — spread bilan yangi massiv
const nusxa2 = [...asl];
nusxa2.push(4);
console.log(asl); // [1, 2, 3] — o'zgarmadi
console.log(nusxa2); // [1, 2, 3, 4]
Funksiyaga argument sifatida:
const sonlar = [3, 1, 4, 1, 5, 9, 2, 6];
// Math.max massiv qabul qilmaydi — alohida argumentlar kerak
console.log(Math.max(3, 1, 4, 1, 5, 9, 2, 6)); // 9
// Spread bilan massivni "yoyib" beramiz
console.log(Math.max(...sonlar)); // 9
Ob'ektda spread
const asosiy = { ism: "Jasur", yosh: 24 };
const qoshimcha = { shahar: "Toshkent", kasb: "Dasturchi" };
// Ob'ektlarni birlashtirish
const toʻliq = { ...asosiy, ...qoshimcha };
console.log(toʻliq);
// { ism: "Jasur", yosh: 24, shahar: "Toshkent", kasb: "Dasturchi" }
Ob'ektni nusxalash va yangilash:
const foydalanuvchi = { ism: "Jasur", yosh: 24, shahar: "Toshkent" };
// Faqat yosh ni o'zgartirgan yangi ob'ekt
const yangilangan = { ...foydalanuvchi, yosh: 25 };
console.log(foydalanuvchi); // { ism: "Jasur", yosh: 24, shahar: "Toshkent" }
console.log(yangilangan); // { ism: "Jasur", yosh: 25, shahar: "Toshkent" }
Bir xil kalit ikki marta bo'lsa — keyingisi ustun keladi. Shuning uchun yosh: 25 ni oxirida yozdik.
Bu pattern React va boshqa frameworklarda state yangilashda juda ko'p ishlatiladi:
const state = { isLoading: false, xato: null, maʼlumot: [] };
// Faqat isLoading ni o'zgartir, qolganlarini saqlb qol
const yangiState = { ...state, isLoading: true };
Rest operatori — yig'ish
Rest ... — spread ning aksi. U "qolgan narsalarni yig'ib, massivga joylashtir" degani.
Tashqi ko'rinish bir xil — ... — lekin ishlashi teskari: spread yoyadi, rest yig'adi.
Funksiya parametrlarida rest
Rest operatori funksiya nechta argument olishini oldindan bilmasangiz ishlatiladi:
function yig'indiHisobla(...sonlar) {
// sonlar — barcha argumentlar massivi
return sonlar.reduce((jami, son) => jami + son, 0);
}
console.log(yig'indiHisobla(1, 2)); // 3
console.log(yig'indiHisobla(1, 2, 3, 4, 5)); // 15
console.log(yig'indiHisobla(10)); // 10
Birinchi argumentlar alohida, qolganlari rest:
function xabarYubor(kimga, mavzu, ...qoʻshimchalar) {
console.log(`Kimga: ${kimga}`);
console.log(`Mavzu: ${mavzu}`);
console.log(`Qo'shimchalar: ${qoʻshimchalar}`);
}
xabarYubor("Ali", "Salom", "rasm.jpg", "hujjat.pdf", "video.mp4");
// Kimga: Ali
// Mavzu: Salom
// Qo'shimchalar: rasm.jpg,hujjat.pdf,video.mp4
Rest har doim eng oxirida bo'lishi kerak — undan keyin boshqa parametr bo'lmaydi.
Destructuring da rest
Oldingi darsda ko'rgan edik — destructuring da ...rest qolgan elementlarni oladi:
// Massivda
const [birinchi, ikkinchi, ...qolganlar] = [1, 2, 3, 4, 5];
console.log(birinchi); // 1
console.log:ikkinchi); // 2
console.log(qolganlar); // [3, 4, 5]
// Ob'ektda
const { ism, ...qolganlar2 } = { ism: "Jasur", yosh: 24, shahar: "Toshkent" };
console.log(ism); // "Jasur"
console.log(qolganlar2); // { yosh: 24, shahar: "Toshkent" }
Spread vs Rest — farqi
Ikkisi ham ... — lekin kontekstga qarab farq qiladi:
Spread — ma'lumotni yoyadi:
[...massiv] → massivni yoyadi
{...ob'ekt} → ob'ektni yoyadi
funksiya(...massiv) → argumentlarni yoyadi
Rest — ma'lumotni yig'adi:
function f(...args) → argumentlarni massivga yig'adi
const [a, ...rest] = arr → qolganlarni massivga yig'adi
const {a, ...rest} = obj → qolganlarni ob'ektga yig'adi
Qoida oddiy: ... chap tomonda (qabul qilayotgan joyda) — rest. ... o'ng tomonda yoki argument sifatida — spread.
// Spread — o'ng tomonda, yoyadi
const arr = [...boshqa];
funksiya(...arr);
// Rest — chap tomonda, yig'adi
const [...qolganlar] = massiv;
function f(...args) {}
Amaliy misollar
Massivdan dublikatlarni olib tashlash:
const takrorli = [1, 2, 2, 3, 3, 3, 4];
const unikal = [...new Set(takrorli)];
console.log(unikal); // [1, 2, 3, 4]
String ni massivga aylantirish:
const soʻz = "Salom";
const harflar = [...soʻz];
console.log(harflar); // ["S", "a", "l", "o", "m"]
Ob'ektdan xususiyat olib tashlab nusxalash:
const foydalanuvchi = {
id: 1,
ism: "Jasur",
parol: "maxfiy123",
email: "jasur@example.com"
};
// parol ni olib tashlab, qolganini olish
const { parol, ...xavfsizMaʼlumot } = foydalanuvchi;
console.log(xavfsizMaʼlumot);
// { id: 1, ism: "Jasur", email: "jasur@example.com" }
Tez-tez uchraydigan xatolar
Rest oxirida bo'lishi kerak
// Xato — rest o'rtada bo'lmaydi
function f(...args, oxirgi) {} // SyntaxError
// To'g'ri — rest eng oxirida
function f(birinchi, ...args) {}
Spread chuqur nusxa qilmaydi
const asl = { ism: "Jasur", manzil: { shahar: "Toshkent" } };
const nusxa = { ...asl };
nusxa.manzil.shahar = "Samarqand"; // ichki ob'ektni o'zgartirdi
console.log(asl.manzil.shahar); // "Samarqand" — asl ham o'zgardi!
Spread faqat birinchi qatlamni nusxalaydi. Ichki ob'ektlar hali ham bir xil xotira manzilini ko'rsatadi. Chuqur nusxa uchun structuredClone() ishlatiladi:
const chuqurNusxa = structuredClone(asl);
chuqurNusxa.manzil.shahar = "Samarqand";
console.log(asl.manzil.shahar); // "Toshkent" — o'zgarmadi
Ob'ektni massivga spread qilish
const ob'ekt = { a: 1, b: 2 };
// Xato — ob'ekt massivga spread qilinmaydi
const arr = [...ob'ekt]; // TypeError
// To'g'ri — Object.values dan foydalaning
const arr2 = [...Object.values(ob'ekt)]; // [1, 2]
Xulosa
... operatori ikki xil vazifani bajaradi — qayerda ishlatilganiga qarab.
Spread — yoyadi. Massiv yoki ob'ekt elementlarini "chiqarib tashlaydi". Birlashtirish, nusxalash, funksiyaga argument sifatida uzatish uchun.
Rest — yig'adi. Qolgan argumentlar yoki elementlarni massiv yoki ob'ektga yig'adi. Funksiya parametrlarida va destructuring da ishlatiladi.
Ikkalasi ham faqat birinchi qatlamni ko'chiradi — ichki ob'ektlar havolasi bo'yicha qoladi. Chuqur nusxa kerak bo'lsa structuredClone() ishlatiladi.
Keyingi dars
22-dars: Massivlar — yaratish va asosiy metodlar — push, pop, shift, unshift, splice, slice