19-bo‘lim
Modullar va zamonaviy JavaScript
import va export, Map va Set, sinflar, getter va setter, ixtiyoriy zanjir, spread va boshqa zamonaviy imkoniyatlar.
Ushbu bo‘lim mundarijasi
Loyiha o'sgach kodni fayllarga bo'lish kerak bo'ladi. Bu bo'limda modullar va oxirgi yillarda qo'shilgan foydali imkoniyatlarni ko'ramiz.
Modul - alohida fayl #
Modullar bir necha faylni talab qiladi, shuning uchun bu misollar namuna sifatida keltirilgan.
// matematika.js
export const PI = 3.14159;
export function kvadrat(son) {
return son * son;
}
export function kub(son) {
return son * son * son;
}
// har faylda bitta standart eksport bo'lishi mumkin
export default function yigindi(...sonlar) {
return sonlar.reduce((a, b) => a + b, 0);
}
// asosiy.js
import yigindi, { PI, kvadrat } from "./matematika.js";
import { kub as kubga } from "./matematika.js";
import * as matematika from "./matematika.js";
console.log(PI); // 3.14159
console.log(kvadrat(4)); // 16
console.log(kubga(3)); // 27
console.log(yigindi(1, 2, 3)); // 6
console.log(matematika.kvadrat(5)); // 25
<!-- Brauzerda type="module" kerak -->
<script type="module" src="asosiy.js"></script>
| Nomlangan | Standart | |
|---|---|---|
| Soni | Cheksiz | Bittasi |
| Import | import { nom } | import nom |
| Nom o'zgartirish | as kerak | Ixtiyoriy |
| Avtomatik to'ldirish | Ishlaydi | Ishlamaydi |
Ko'p jamoalar faqat nomlangan eksportni ishlatadi:
export function foydalanuvchiOlish() { }
export function foydalanuvchiSaqlash() { }
Sabab: standart eksportni har faylda turlicha nomlash mumkin, bu chalkashlik tug'diradi:
import A from "./foydalanuvchi.js";
import B from "./foydalanuvchi.js"; // bir xil narsa, boshqa nom
Nomlangan eksportda esa nom bir xil qoladi va tahrirlagich uni avtomatik topadi.
file:// orqali ochib bo'lmaydiAccess to script at 'file:///.../asosiy.js' from origin 'null'
has been blocked by CORS policy
Modullar HTTP orqali yuklanishi shart. HTML faylni ikki marta bosib ochsangiz ishlamaydi.
Yechim - oddiy server ishga tushiring:
npx serve
python3 -m http.server
php -S localhost:8000
Modullarning boshqa xususiyatlari:
- Har doim
strictrejimda ishlaydi; - O'z ko'lamiga ega - global o'zgaruvchi yaratmaydi;
- Bir marta yuklanadi va keshlanadi;
deferkabi ishlaydi - HTML tayyor bo'lgach bajariladi;- Yuqoriga
awaitqo'yish mumkin (top-level await).
Node.js da .mjs kengaytmasi yoki package.json da
"type": "module" kerak. Aks holda Node require ni kutadi.
Map - istalgan kalitli lug'at #
const yoshlar = new Map();
yoshlar.set("Husanboy", 25);
yoshlar.set("Malika", 22);
// Obyekt ham kalit bo'la oladi
const kalit = { id: 1 };
yoshlar.set(kalit, "obyekt kaliti");
console.log("get :", yoshlar.get("Husanboy"));
console.log("has :", yoshlar.has("Malika"));
console.log("size :", yoshlar.size);
console.log("Obyekt kalit:", yoshlar.get(kalit));
console.log("Yo'q kalit:", yoshlar.get("Yo'q"));
yoshlar.delete("Malika");
console.log("delete keyin:", yoshlar.size);
// Aylanish - qo'shilish tartibi saqlanadi
const oddiy = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (const [k, q] of oddiy) {
console.log(` ${k} -> ${q}`);
}
console.log("Massivga :", [...oddiy.keys()].join(", "));
get : 25
has : true
size : 3
Obyekt kalit: obyekt kaliti
Yo'q kalit: undefined
delete keyin: 2
a -> 1
b -> 2
c -> 3
Massivga : a, b, c
Map yoki oddiy obyekt?| Xususiyat | Obyekt | Map |
|---|---|---|
| Kalit turi | Faqat satr va Symbol | Istalgan qiymat |
| Hajm | Object.keys().length | .size |
| Tartib | Butun sonlar oldinga suriladi | Qo'shilish tartibi |
| Meros olingan kalitlar | Bor (toString va h.k.) | Yo'q |
| Tez-tez qo'shish/o'chirish | Sekinroq | Tezroq |
Obyektning kutilmagan xatti-harakati:
const obyekt = {};
obyekt[1] = "son";
obyekt["1"] = "satr";
console.log(Object.keys(obyekt)); // ["1"] - bittasi!
Kalit avtomatik satrga aylanadi.
Tartib bilan ham muammo:
const menyu = { "10": "o'n", "2": "ikki", "b": "harf" };
console.log(Object.keys(menyu)); // ["2", "10", "b"]
Butun sonlarga o'xshash kalitlar oldinga suriladi va o'sish tartibida saralanadi.
Qoida: kalitlar oldindan ma'lum bo'lsa - obyekt; dinamik
yoki satr bo'lmasa - Map.
Set - takrorlanmaydigan to'plam #
const raqamlar = new Set([1, 2, 2, 3, 3, 3]);
console.log("Hajmi :", raqamlar.size);
console.log("has(2) :", raqamlar.has(2));
raqamlar.add(4);
raqamlar.add(4); // takror - qo'shilmaydi
console.log("add keyin:", raqamlar.size);
// Massivdagi takrorlarni olib tashlash
const takrorlar = ["a", "b", "a", "c", "b"];
const noyob = [...new Set(takrorlar)];
console.log("Noyob :", noyob.join(", "));
// To'plamlar ustida amallar
const a = new Set([1, 2, 3]);
const b = new Set([2, 3, 4]);
const kesishma = [...a].filter((x) => b.has(x));
const birlashma = [...new Set([...a, ...b])];
const ayirma = [...a].filter((x) => !b.has(x));
console.log("Kesishma:", kesishma.join(", "));
console.log("Birlashma:", birlashma.join(", "));
console.log("Ayirma :", ayirma.join(", "));
Hajmi : 3
has(2) : true
add keyin: 4
Noyob : a, b, c
Kesishma: 2, 3
Birlashma: 1, 2, 3, 4
Ayirma : 1
Sinflar #
class Talaba {
#maxfiyBall = 0; // shaxsiy maydon
static soni = 0; // statik maydon
constructor(ism, yosh) {
this.ism = ism;
this.yosh = yosh;
Talaba.soni++;
}
get ball() {
return this.#maxfiyBall;
}
set ball(qiymat) {
if (qiymat < 0 || qiymat > 100) {
throw new RangeError("Ball 0-100 oralig'ida bo'lishi kerak");
}
this.#maxfiyBall = qiymat;
}
tanishtirish() {
return `${this.ism}, ${this.yosh} yosh`;
}
static taqqoslash(a, b) {
return b.ball - a.ball;
}
}
class Magistr extends Talaba {
constructor(ism, yosh, mavzu) {
super(ism, yosh);
this.mavzu = mavzu;
}
tanishtirish() {
return super.tanishtirish() + `, mavzu: ${this.mavzu}`;
}
}
const birinchi = new Talaba("Husanboy", 25);
birinchi.ball = 92;
const ikkinchi = new Magistr("Aziza", 27, "Sun'iy intellekt");
ikkinchi.ball = 88;
console.log(birinchi.tanishtirish());
console.log(ikkinchi.tanishtirish());
console.log("Ball (getter):", birinchi.ball);
console.log("Talabalar soni:", Talaba.soni);
console.log("Magistr Talabami?:", ikkinchi instanceof Talaba);
try {
birinchi.ball = 150;
} catch (xato) {
console.log("Setter tekshiruvi:", xato.message);
}
console.log("Shaxsiy maydon ko'rinadimi?:", Object.keys(birinchi).join(", "));
Husanboy, 25 yosh
Aziza, 27 yosh, mavzu: Sun'iy intellekt
Ball (getter): 92
Talabalar soni: 2
Magistr Talabami?: true
Setter tekshiruvi: Ball 0-100 oralig'ida bo'lishi kerak
Shaxsiy maydon ko'rinadimi?: ism, yosh
# bilan haqiqiy shaxsiy maydonIlgari shaxsiylikni kelishuv bilan belgilashardi:
this._maxfiy = 5; // "tegmang" degan ishora, lekin ochiq
# esa haqiqiy himoya beradi:
class A {
#maxfiy = 5;
}
const a = new A();
a.#maxfiy; // SyntaxError - tashqaridan murojaat mumkin emas
Object.keys(a); // [] - ko'rinmaydi
JSON.stringify(a); // {} - serializatsiyaga tushmaydi
Bu 5-bo'limdagi berkitma (closure) naqshining sinflardagi muqobili - lekin ancha qulayroq.
Shaxsiy metod ham bo'ladi:
class A {
#ichkiHisob() { }
}
Tekshirish uchun in operatori ishlatiladi:
static bormi(obyekt) {
return #maxfiy in obyekt;
}
Ixtiyoriy zanjir va nullish #
const foydalanuvchi = {
ism: "Kamola",
manzil: { shahar: "Farg'ona" },
sozlama: { bildirishnoma: false, hajm: 0 }
};
console.log("Mavjud :", foydalanuvchi.manzil?.shahar);
console.log("Mavjud emas:", foydalanuvchi.ish?.lavozim);
console.log("Chuqur :", foydalanuvchi.ish?.kompaniya?.nomi);
// Metod chaqirish
console.log("Metod yo'q :", foydalanuvchi.hisobla?.());
// Massiv elementi
const royxat = null;
console.log("Massiv :", royxat?.[0]);
// ?? bilan birga
console.log("false va ??:", foydalanuvchi.sozlama.bildirishnoma ?? true);
console.log("false va ||:", foydalanuvchi.sozlama.bildirishnoma || true);
console.log("0 va ?? :", foydalanuvchi.sozlama.hajm ?? 14);
console.log("0 va || :", foydalanuvchi.sozlama.hajm || 14);
// ??= operatori
const sozlama = { til: null };
sozlama.til ??= "uz";
sozlama.rejim ??= "yorug'";
console.log("??= natijasi:", JSON.stringify(sozlama));
Mavjud : Farg'ona
Mavjud emas: undefined
Chuqur : undefined
Metod yo'q : undefined
Massiv : undefined
false va ??: false
false va ||: true
0 va ?? : 0
0 va || : 14
??= natijasi: {"til":"uz","rejim":"yorug'"}
Spread va rest #
// Massivda
const a = [1, 2];
const b = [3, 4];
console.log("Birlashtirish:", [...a, ...b]);
console.log("Nusxa :", [...a]);
console.log("Satrdan :", [..."abc"]);
console.log("Set dan :", [...new Set([1, 1, 2])]);
// Obyektda
const asos = { x: 1, y: 2 };
console.log("Obyekt spread:", { ...asos, z: 3 });
// Funksiyada
function yigindi(...sonlar) {
return sonlar.reduce((s, n) => s + n, 0);
}
console.log("Rest :", yigindi(1, 2, 3, 4));
console.log("Spread argument:", Math.max(...[5, 2, 9]));
// Destrukturizatsiyada rest
const { x, ...qolgani } = { x: 1, y: 2, z: 3 };
console.log("Obyekt rest :", x, JSON.stringify(qolgani));
const [birinchi, ...boshqalar] = [1, 2, 3, 4];
console.log("Massiv rest :", birinchi, boshqalar.join(","));
Birlashtirish: [ 1, 2, 3, 4 ]
Nusxa : [ 1, 2 ]
Satrdan : [ 'a', 'b', 'c' ]
Set dan : [ 1, 2 ]
Obyekt spread: { x: 1, y: 2, z: 3 }
Rest : 10
Spread argument: 9
Obyekt rest : 1 {"y":2,"z":3}
Massiv rest : 1 2,3,4
Foydali yangi metodlar #
// Massiv
console.log("at(-1) :", [1, 2, 3].at(-1));
console.log("flat :", [1, [2, [3]]].flat(2));
console.log("flatMap :", [1, 2].flatMap((x) => [x, x * 10]));
console.log("toSorted :", [3, 1, 2].toSorted((a, b) => a - b));
console.log("toReversed :", [1, 2, 3].toReversed());
console.log("with :", [1, 2, 3].with(1, 99));
console.log("findLast :", [1, 5, 3, 5].findLast((x) => x === 5));
// Satr
console.log("replaceAll :", "a-b-c".replaceAll("-", "+"));
console.log("trimStart :", JSON.stringify(" x".trimStart()));
// Struktura
const asl = { ichki: { son: 1 } };
const nusxa = structuredClone(asl);
nusxa.ichki.son = 99;
console.log("structuredClone:", asl.ichki.son);
at(-1) : 3
flat : [ 1, 2, 3 ]
flatMap : [ 1, 10, 2, 20 ]
toSorted : [ 1, 2, 3 ]
toReversed : [ 3, 2, 1 ]
with : [ 1, 99, 3 ]
findLast : 5
replaceAll : a+b+c
trimStart : "x"
structuredClone: 1
Object.groupBy - juda yangiES2024 da guruhlash uchun tayyor metod qo'shilgan:
Object.groupBy([1, 2, 3, 4], (n) => (n % 2 === 0 ? "juft" : "toq"));
// { toq: [1, 3], juft: [2, 4] }
Lekin u Node 21 va 2024-yil o'rtasidan keyingi brauzerlarda paydo bo'lgan - shuning uchun bu yerda ishga tushirilmadi.
Hozircha reduce bilan yozgan ma'qul (7-bo'limdagi kabi):
const guruhlar = sonlar.reduce((natija, n) => {
const kalit = n % 2 === 0 ? "juft" : "toq";
(natija[kalit] ??= []).push(n);
return natija;
}, {});
Yangi imkoniyatni ishlatishdan oldin caniuse.com yoki MDN dagi moslik jadvalini tekshiring - foydalanuvchilaringizning brauzeri uni qo'llab-quvvatlamasligi mumkin.
sort, reverse va splice asl massivni buzadi. Bu
kutilmagan xatolarga olib keladi:
function engKatta(royxat) {
return royxat.sort((a, b) => b - a)[0]; // ASLINI o'zgartirdi!
}
const ballar = [70, 95, 80];
engKatta(ballar);
console.log(ballar); // [95, 80, 70] - tartib buzildi
ES2023 dan nusxa qaytaradigan variantlar bor:
| Eski (buzadi) | Yangi (nusxa) |
|---|---|
sort() | toSorted() |
reverse() | toReversed() |
splice() | toSpliced() |
massiv[i] = x | with(i, x) |
function engKatta(royxat) {
return royxat.toSorted((a, b) => b - a)[0]; // xavfsiz
}
Node 20 va 2023-yildan keyingi brauzerlar qo'llab-quvvatlaydi.
Yorliqli shablon (tagged template) #
function xavfsiz(qismlar, ...qiymatlar) {
return qismlar.reduce((natija, qism, i) => {
const qiymat = qiymatlar[i - 1];
const tozalangan = String(qiymat)
.replaceAll("&", "&")
.replaceAll("<", "<")
.replaceAll(">", ">");
return natija + tozalangan + qism;
});
}
const foydalanuvchiMatni = "<script>hujum()</script>";
console.log(xavfsiz`Salom, ${foydalanuvchiMatni}!`);
// Oddiy shablon bilan taqqoslash
console.log(`Salom, ${foydalanuvchiMatni}!`);
Salom, <script>hujum()</script>!
Salom, <script>hujum()</script>!
- Ikki fayl yaratib,
exportvaimportbilan bog'lang. - Nomlangan va standart eksport farqini tushuntiring.
Mapda obyektni kalit sifatida ishlating.- Obyektda
1va"1"kalitlari bir xil bo'lishini ko'rsating. Setbilan massivdagi takrorlarni olib tashlang.- Sinf yozib,
#bilan shaxsiy maydon qo'shing. get/setbilan qiymatni tekshiring.?.va??ni0vafalseqiymatlar bilan sinang.toSortedvasortfarqini isbotlang.- Yorliqli shablon bilan HTML ni tozalang.
Xulosa #
export/importkodni fayllarga bo'ladi.- Brauzerda
type="module"va HTTP server kerak. - Modullar strict rejimda ishlaydi va o'z ko'lamiga ega.
- Nomlangan eksport afzal - nom bir xil qoladi.
Mapistalgan turdagi kalitni qabul qiladi va tartibni saqlaydi.- Obyektda kalit avtomatik satrga aylanadi.
Settakrorlarni olib tashlaydi.#bilan haqiqiy shaxsiy maydon yaratiladi.get/setqiymatni tekshirish imkonini beradi.??faqatnull/undefinedda ishlaydi,||esa0va""da ham.toSorted,toReversed,withaslini buzmaydi.- Yorliqli shablon bilan xavfsiz HTML yig'iladi.
Keyingi va oxirgi bo'limda hamma bilimni birlashtirib, to'liq ilova yozamiz.
O‘qish tarixini saqlamoqchimisiz?
Tizimga kirsangiz, tugatgan bo‘limlaringiz saqlanadi va qoldirgan joyingizdan davom etasiz.
Xatolik topdingizmi?
Imlo xatosi, ishlamaydigan kod yoki noto‘g‘ri ma‘lumotni ko‘rsangiz - bizga xabar bering. Har bir xabar administrator tomonidan ko‘rib chiqiladi.