Scope — global, function, block scope

~15 daq · JavaScript · Funksiyalar chuqurroq

Muammodan boshlaylik

function hisoblash() {
  let natija = 42;
}

console.log(natija); // ReferenceError: natija is not defined

Nima uchun? natija funksiya ichida e'lon qilindi — tashqaridan ko'rinmaydi. Bu — scope.

Scope tushunmasdan yozilgan kodda o'zgaruvchilar bir-birini "bosib ketadi", kutilmagan qiymatlar chiqadi, xatolarni topish qiyinlashadi.


Scope nima?

Scope — o'zgaruvchi "ko'rinadigan" hudud. O'zgaruvchi qayerda e'lon qilingan bo'lsa — faqat shu hududda va uning ichida ko'rinadi.

Hayotiy o'xshatma: uy va xonalar. Uyning umumiy zali — hamma ko'radi. Yotoqxonadagi narsa — faqat yotoqxonada ko'rinadi. Mehmonxonadan yotoqxonadagi narsani ko'rib bo'lmaydi.


Global Scope

Funksiya yoki blok tashqarisida e'lon qilingan o'zgaruvchi — global. Hamma joydan ko'rinadi.

const dasturNomi = "DevDocs"; // ← global

function ko_rsat() {
  console.log(dasturNomi); // ✅ ko'rinadi
}

ko'rsat(); // "DevDocs"
console.log(dasturNomi); // ✅ ko'rinadi

Global o'zgaruvchilar qulay ko'rinadi — lekin muammo tug'diradi. Katta loyihalarda qaysi funksiya qaysi global o'zgaruvchini o'zgartirayotganini kuzatish qiyinlashadi. Global o'zgaruvchilar minimallashtiriladi.


Function Scope

var bilan e'lon qilingan o'zgaruvchi — funksiya ichida ko'rinadi, tashqarida yo'q.

function hisoblash() {
  var ichki = 10;
  console.log(ichki); // ✅ 10
}

hisoblash();
console.log(ichki); // ❌ ReferenceError

var ning muammosi — blok scope ni tushunmaydi:

if (true) {
  var x = 5; // ← var blokni e'tiborsiz qoldiradi
}
console.log(x); // 5 — tashqarida ham ko'rinadi!

Shu sababli var ishlatilmaydi — let va const ishlatiladi.


Block Scope

let va const — blok {} ichida e'lon qilinsa, faqat shu blokda ko'rinadi.

if (true) {
  let y = 5;
  const z = 10;
  console.log(y, z); // ✅ 5, 10
}

console.log(y); // ❌ ReferenceError
console.log(z); // ❌ ReferenceError

for sikli ham blok:

for (let i = 0; i < 3; i++) {
  // i faqat shu yerda ko'rinadi
}
console.log(i); // ❌ ReferenceError

Nima uchun shunday?

Nima uchun var emas let/const?

var — JavaScript ning eski versiyasidan. Block scope tushunmaydi, hoisting bilan g'alati ishlaydi. let va const bu muammolarni hal qilish uchun ES6 da kiritildi.

// var — xavfli
for (var i = 0; i < 3; i++) { }
console.log(i); // 3 — sikl tashqarisida ham ko'rinadi!

// let — xavfsiz
for (let j = 0; j < 3; j++) { }
console.log(j); // ❌ ReferenceError — to'g'ri xulq

Scope zanjiri — Lexical Scope

Ichki scope tashqi scope dagi o'zgaruvchilarni ko'radi — lekin teskari emas.

const tashqi = "tashqi";

function tashqiFn() {
  const oraliq = "oraliq";

  function ichkiFn() {
    const ichki = "ichki";
    console.log(tashqi);  // ✅ ko'rinadi — yuqoriga qaraydi
    console.log(oraliq);  // ✅ ko'rinadi
    console.log(ichki);   // ✅ ko'rinadi
  }

  console.log(ichki); // ❌ ReferenceError — pastga qaray olmaydi
}

O'zgaruvchi topilmasa — JavaScript yuqoriga, tashqi scope ga qaraydi. Bu zanjir global scope gacha davom etadi. Topilmasa — ReferenceError.


Shadowing — ustiga yozish

Ichki scope da tashqi scope dagi o'zgaruvchi bilan bir xil nom ishlatilsa — ichki o'zgaruvchi tashqisini "yashiradi":

const ism = "Ali";

function ko'rsat() {
  const ism = "Vali"; // ← tashqi "Ali" ni yashiradi
  console.log(ism);   // "Vali"
}

ko'rsat();
console.log(ism); // "Ali" — tashqi o'zgarmadi

Bu xato emas — lekin chalkashlik tug'dirishi mumkin. Bir xil nomdan qochish yaxshiroq.


Tez-tez uchraydigan xatolar

var bilan sikl va asinxron:

for (var i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// 3, 3, 3 — var funksiya scope, sikl tugaganda i=3

for (let i = 0; i < 3; i++) {
  setTimeout(() => console.log(i), 100);
}
// 0, 1, 2 — let block scope, har iteratsiyada yangi i

Global o'zgaruvchini tasodifan yaratish:

function hisoblash() {
  natija = 42; // ← let/const yo'q — global bo'lib qoladi!
}
hisoblash();
console.log(natija); // 42 — global, bu xato

Bir xil nom — shadowing chalkashligi:

const data = fetchData();

function qayta_ishlash() {
  const data = []; // ← tashqi data ni yashirdi
  // ... tashqi data ga murojaat qilib bo'lmaydi
}

Xulosa

Global scope — hamma joydan ko'rinadi. Minimallashtiriladi.

Function scope — var funksiya ichida ko'rinadi. var ishlatilmaydi.

Block scope — let va const {} ichida ko'rinadi. Tashqarida yo'q.

Ichki scope tashqi scope ni ko'radi — teskari emas. O'zgaruvchi topilmasa — yuqoriga qaraladi (scope zanjiri).


Keyingi dars

10-dars: Hoisting — o'zgaruvchi va funksiyalar qanday ko'tariladi