25 август 2025

Modullar, tanishtirish

Bizning dasturimiz kattalashib borishi bilan biz uni “modullar” deb nomlangan bir nechta fayllarga ajratishni xohlaymiz. Modul odatda foydali funktsiyalar klassini yoki kutubxonasini o’z ichiga oladi.

Uzoq vaqt davomida JavaScript til darajasidagi modul sintaksisiz mavjud edi. Bu muammo emas edi, chunki dastlab skriptlar kichik va sodda edi. Shunday qilib, ehtiyoj yo’q edi.

Ammo oxir-oqibat skriptlar tobora murakkablashib bordi, shuning uchun hamjamiyat kodlarni modullarga joylashtirishning turli usullarini ixtiro qildi.

Masalan:

  • AMD – dastlab kutubxona tomonidan amalga oshirilgan eng qadimgi modul tizimlaridan biri request.js.
  • CommonJS – Node.js server uchun yaratilgan modul tizimi.
  • UMD – yana bitta modul tizimi, universal sifatida tavsiya etilgan, AMD va CommonJS bilan mos keladi.

Endi bularning barchasi asta-sekin tarixning bir qismiga aylanadi, ammo biz ularni eski skriptlarda topishimiz mumkin. Til darajasidagi modul tizimi standartda 2015 yilda paydo bo’lgan va o’sha paytdan boshlab asta-sekin rivojlanib borgan va hozirda barcha yirik brauzerlar va Node.js tomonidan qo’llab quvatlanadi.

Modul nima?

Modul – bu shunchaki fayl, bitta skript, shu kabi sodda.

export va import direktivalari modullar o’rtasida funksiyalarni almashtirishga imkon beradi:

  • export Fayl tashqarisidan kirish mumkin bo’lgan kalit so’zlar o’zgaruvchanlar va funktsiyalarni belgilaydi.
  • import funksiyalarni boshqa modullardan import qilishga imkon beradi.

Masalan, funktsiyani eksport qiladigan sayHi.js faylimiz bo’lsa:

// 📁 sayHi.js
export function sayHi(user) {
  alert(`Salom, ${user}!`);
}

…Keyin boshqa fayl uni import qilishi va ishlatishi mumkin:

// 📁 main.js
import {sayHi} from './sayHi.js';

alert(sayHi); // funktisya...
sayHi('John'); // Salom, John!

Ushbu qo’llanmada biz diqqatni tilning o’ziga qaratamiz, ammo biz demo muhit sifatida brauzerdan foydalanamiz, shuning uchun brauzerda modullarning qanday ishlashini ko’rib chiqamiz.

Modullardan foydalanish uchun biz <script type="module"> atributini quyidagicha o’rnatishimiz kerak:

Natija
say.js
index.html
export function sayHi(user) {
  return `Salom, ${user}!`;
}
<!DOCTYPE html>
<script type="module">
  import { sayHi } from "./say.js";

  document.body.innerHTML = sayHi("John");
</script>

Brauzer avtomatik ravishda importni oladi va baholaydi, so’ngra skriptni bajaradi.

Asosiy modul xususiyatlari

“Oddiy” skriptlar bilan taqqoslaganda modullar bilan qanday farq bor?

Brauzerda ham, server tomonida ham JavaScript uchun amal qiladigan asosiy xususiyatlar mavjud.

Har doim “use strict”

Modullar doimo use strict dan foydalanadilar. Masalan, e’lon qilinmagan o’zgaruvchanga tayinlash xatoga yo’l qo’yadi.

<script type="module">
  a = 5; // xato
</script>

Bu yerda biz uni brauzerda ko’rishimiz mumkin, ammo har qanday modul uchun ham xuddi shunday ishlaydi.

Maxsus o’zgaruvchan ko’lam

Har bir modul o’zining yuqori darajadagi doirasiga ega. Boshqacha aytganda, moduldan yuqori darajadagi o’zgaruvchanlar va funktsiyalar boshqa skriptlarda ko’rinmaydi.

Quyidagi misolda ikkita skript import qilingan va hello.js user.js da e’lon qilingan user o’zgaruvchanidan foydalanishga harakat qiladi va bajarilmaydi:

Natija
hello.js
user.js
index.html
alert(user); // no such variable (each module has independent variables)
let user = "John";
<!DOCTYPE html>
<script type="module" src="user.js"></script>
<script type="module" src="hello.js"></script>

Modullar tashqaridan kirishni xohlagan narsalarini export qilishlari va kerakli narsalarini import qilishlari kutilmoqda.

Shuning uchun biz user.js ni index.html o’rniga to’g’ridan-to’g’ri hello.js ga import qilishimiz kerak.

Bu to’g’ri variant:

Natija
hello.js
user.js
index.html
import { user } from "./user.js";

document.body.innerHTML = user; // John
export let user = "John";
<!DOCTYPE html>
<script type="module" src="hello.js"></script>

Brauzerda har bir <script type="module"> uchun mustaqil yuqori darajadagi ko’lam mavjud:

<script type="module">
  // O'zgaruvchan faqat ushbu modul skriptida ko'rinadi
  let user = "John";
</script>

<script type="module">
  alert(user); // Error: user is not defined
</script>

Agar biz chindan ham “global” brauzer ichida o’zgaruvchanni yaratishimiz kerak bo’lsa, uni window ga aniq belgilashimiz va window.user sifatida kirishimiz mumkin. Ammo bu yaxshi sababni talab qiladigan istisno.

Import qilinganida modul kodi faqat birinchi marta baholanadi

Agar bir xil modul boshqa bir qancha joylarga import qilingan bo’lsa, uning kodi faqat birinchi marta bajariladi, keyin eksport barcha importerlarga beriladi.

Bu muhim oqibatlarga olib keladi. Keling, buni misollarda ko’rib chiqaylik.

Birinchidan, agar modul kodini bajarish xabarni ko’rsatish kabi nojo’ya ta’sirlarni keltirib chiqarsa, uni bir necha marta import qilish uni faqat bir marta bajaradi, birinchi marta:

// 📁 alert.js
alert("Modul baholandi!");
// Xuddi shu modulni turli xil fayllardan import qiling

// 📁 1.js
import `./alert.js`; // Modul baholandi!

// 📁 2.js
import `./alert.js`; // (hech narsa)

Amalda, yuqori darajadagi modul kodi asosan ishga tushirish uchun ishlatiladi. Biz ma’lumotlar tuzilmalarini yaratamiz, ularni oldindan to’ldiramiz va agar biror narsa qayta ishlatilishini istasak – uni eksport qilamiz.

Endi yanada rivojlangan misol.

Aytaylik, modul obyektni eksport qiladi: