IlmHamroh
JavaScript Full-stack/24-qism. Node.js7/55-dars14 daqiqa
Mundarija (26)

Node.js global obyektlari: globalThis, process, Buffer va brauzer farqi

Qisqacha: Node'da window va document yo'q — bu brauzerning sahifa bilan bog'liq obyektlari. Umumiy global obyekt ikkalasida ham globalThis deb ataladi (Node'da eski nomi — global). Node'da faqat unga xos globallar bor: process, Buffer, setImmediate. Shu bilan birga Node 24 da ko'plab veb API'lar ham global: fetch, URL, URLPattern, AbortController, structuredClone, performance, crypto, hatto navigator. ESM faylda require, __dirname, __filename yo'q — ularning o'rnida import.meta.dirname va import.meta.filename.

Bu darsda

  • Node 24 da qaysi globallar bor, qaysilari yo'qligini o'lchov asosida bilasiz.
  • globalThis, global va window farqini tushuntira olasiz.
  • ESM faylda __dirname o'rniga import.meta.dirname ishlatasiz va nega CommonJS'da u "global" ekanini tushunasiz.
  • Taymerlar Node'da son emas, obyekt qaytarishini va undan nima foyda borligini bilasiz.
  • Ham brauzerda, ham Node'da ishlaydigan kod yozishda qaysi globallarga tayanish xavfsizligini aniqlaysiz.

Oldin bilishingiz kerak: Node.js nima: runtime, V8 va libuv, CommonJS va ESM bilan o'zaro ishlash, Event loop'ni bloklash.

1. Nega bu kerak?

Aziz 13-qismda brauzer uchun yozgan kichik funksiyasini Node'ga ko'chirdi. Funksiya oxirgi kursni localStorage ga saqlar edi. Terminalda birinchi ishga tushirishdayoq:

text
ReferenceError: localStorage is not defined

Tarjimasi: "localStorage aniqlanmagan". Keyin u boshqa bir maqoladan __dirname ni ko'chirdi — yana ReferenceError. Va nihoyat, Node'da window umuman yo'qligini ko'rib hayron qoldi: "Unda fetch qayerdan keldi?"

Bu chalkashlikning sababi bitta: JavaScript tili bitta, lekin global narsalar (hech qanday import siz ishlatiladigan nomlar) har muhitda o'zicha. Node.js nima darsida runtime — "til + atrofdagi asboblar" ekanini ko'rdingiz. Bu dars aynan shu asboblarning ro'yxati: qaysi biri umumiy, qaysi biri faqat Node'da, qaysi biri faqat brauzerda.

O'xshatish: ikkita oshxona. Pichoq, qozon, tuz — ikkalasida ham bor (til va umumiy API'lar). Tandir faqat bittasida, mikroto'lqinli pech — faqat boshqasida. Retseptni ko'chirayotganda qaysi asbob qayerda borligini bilishingiz kerak.

2. Uch qatlam globallar

2.1 Til, umumiy veb API, muhitga xos

Node va brauzerdagi globallarni uch guruhga ajratish qulay:

Guruh Misollar Qayerda
Tilning o'zi (ECMAScript) Math, JSON, Promise, Map, Array hamma joyda
Umumiy veb API'lar fetch, URL, AbortController, TextEncoder, structuredClone, crypto, performance brauzer va Node 24
Faqat brauzer window, document, localStorage, alert, requestAnimationFrame brauzer
Faqat Node process, Buffer, global, setImmediate Node

Diagrammada ikki muhitning kesishmasiga qarang. Ikkala tarafda ishlaydigan kod faqat o'rtadagi qismga tayanadi:

flowchart LR
  B["Faqat brauzer<br/>window, document,<br/>localStorage, alert"] --- U
  U["Umumiy<br/>Math, JSON, Promise,<br/>fetch, URL, crypto,<br/>structuredClone"] --- N
  N["Faqat Node<br/>process, Buffer,<br/>setImmediate, global"]

Ikkinchi qator — Node so'nggi yillarda eng ko'p o'zgargan joy. Node 18 gacha fetch uchun alohida paket o'rnatilardi. Hozir veb standartlariga mos API'lar Node'ga to'g'ridan qo'shilmoqda: kod ikki muhitda bir xil ishlashi uchun. Next.js runtime'lar darsida Edge runtime aynan shu umumiy qatlamga tayanishini ko'rgansiz.

2.2 O'lchov: Node 24 da nima bor

Kanon tajribasi ESM faylda typeof bilan 28 ta nomni tekshirdi. Quyidagi blok shuning qisqa nusxasi — u tekshiruvchida haqiqiy Node 24 da ishga tushiriladi. Saytda «Ishga tushir» tugmasi yo'q: kodni global.mjs ga saqlab, terminalda node global.mjs deb yurgizing.

js
const names = [
  "window", "document", "localStorage", "alert",
  "globalThis", "global", "process", "Buffer", "setImmediate",
  "fetch", "URL", "URLPattern", "AbortController", "TextEncoder",
  "structuredClone", "crypto", "performance", "navigator",
  "WebSocket", "require", "__dirname",
];
for (const name of names) {
  console.log(name.padEnd(16), typeof globalThis[name]);
}

Konsolda:

text
window           undefined
document         undefined
localStorage     undefined
alert            undefined
globalThis       object
global           object
process          object
Buffer           function
setImmediate     function
fetch            function
URL              function
URLPattern       function
AbortController  function
TextEncoder      function
structuredClone  function
crypto           object
performance      object
navigator        object
WebSocket        function
require          undefined
__dirname        undefined

Uchta kutilmagan natija:

  1. navigator bor. Node 21 dan beri u global. Lekin brauzerdagiga o'xshamaydi: unda faqat hardwareConcurrency, language, languages, platform, userAgent va locks bor. Kanonda navigator.userAgent — "Node.js/24", hardwareConcurrency — 16 (mantiqiy yadrolar soni).
  2. URLPattern bor. Node 24 da u global — brauzerdagi kabi URL naqshlarini moslashtiradi.
  3. require va __dirname yo'q. Bu fayl ESM (.mjs). Nega — keyingi bo'limda.

2.3 Brauzerda ham sinang

Saytdagi «Ishga tushir» oynasi — haqiqiy brauzer. Quyidagi blok ikkala muhitda ham ishlaydi, lekin natija har xil chiqadi. Tekshiruvchi uni Node'da yurgizadi, shuning uchun pastdagi chiqish — Node'niki:

js
const env = typeof window !== "undefined" ? "brauzer" : "Node";
console.log(`muhit: ${env}`);
console.log(`URL bor: ${typeof URL === "function"}`);
console.log(`process bor: ${typeof process === "object"}`);

Konsolda:

text
muhit: Node
URL bor: true
process bor: true

«Ishga tushir» ni bosing — natija oynasida muhit: brauzer, process bor: false chiqadi. Kod bir xil, globallar boshqa.

Tekshirib ko'ring: Node 24 da typeof fetch va typeof localStorage nima qaytaradi?

Javob

"function" va "undefined". fetch — umumiy veb API, Node 18 dan beri global. localStorage esa brauzer sahifasining saqlash joyi — Node'da sukut bo'yicha yo'q (pastda ko'rasiz: faqat eksperimental bayroq bilan).

3. globalThis, global va window

3.1 Bitta nom — hamma muhitda

Har muhitda "global obyekt" bor — barcha globallar uning xususiyatlari (property). Tarixan uning nomi har joyda boshqa edi: brauzerda window (worker'da self), Node'da global. Ikkala muhitda ishlaydigan kod yozish uchun ES2020 bitta umumiy nom kiritdi — globalThis.

js
console.log(typeof global, global === globalThis);
globalThis.appName = "valyuta";
console.log(appName);

Konsolda:

text
object true
valyuta

global — Node'dagi eski nom, u aynan globalThis ning o'zi. Yangi kodda globalThis yozing: u brauzerda ham, Node'da ham, worker'da ham ishlaydi. globalThis ga xususiyat qo'shsangiz, u hamma joydan ko'rinadi — xuddi appName kabi. Bu qulay tuyuladi, lekin global o'zgaruvchilar kodni chalkashtiradi. Faqat juda kerak bo'lganda (masalan, polyfill) ishlating.

3.2 var global emas — modulda

Brauzerdagi oddiy <script> da yuqori darajadagi var narx = 1 avtomatik window.narx bo'ladi. Node'da esa har fayl — modul. Modul o'z scope'iga ega (Modul semantikasi), shuning uchun var ham global obyektga tushmaydi:

js
var rate = 11903.15;
console.log(globalThis.rate);
console.log(this);

Konsolda:

text
undefined
undefined

ESM modulida yuqori darajadagi this ham undefined. CommonJS'da esa boshqacha — keyingi bo'limda ko'rasiz.

4. __dirname va import.meta.dirname

4.1 Nega ESM'da __dirname yo'q

CommonJS va ESM bilan o'zaro ishlash darsida ko'rgansiz: CommonJS faylini Node bajarishdan oldin funksiyaga o'raydi. require, module, exports, __filename, __dirname — aslida o'sha funksiyaning parametrlari. Ular global emas, har faylga alohida beriladi. Ichki tuzilmasini CommonJS ichidan darsida ochamiz. Hozir natijani ko'ring — bu blok .cjs sifatida bajariladi:

js
var rate = 11903.15;
console.log(globalThis.rate);
console.log(this === module.exports);
console.log(typeof require, typeof module, typeof exports);
console.log(typeof __dirname, typeof __filename);

Konsolda:

text
undefined
true
function object object
string string

CommonJS'da var ham global emas (fayl funksiya ichida), this esa module.exports ga teng. __dirname bor, chunki o'ralgan funksiya uni parametr qilib oladi. ESM fayllar o'ralmaydi — shuning uchun ularda bu nomlar yo'q.

4.2 ESM'dagi o'rinbosar

ESM'da modul haqidagi ma'lumot import.meta obyektida. Dinamik import va top-level await darsida import.meta.url ni ko'rgansiz. Node 20.11 va 21.2 dan beri yana ikkita xususiyat bor:

CommonJS ESM (Node 20.11+) Nima
__filename import.meta.filename joriy faylning to'liq yo'li
__dirname import.meta.dirname joriy fayl turgan papka
— import.meta.url file:///… ko'rinishidagi URL

Yo'l har kompyuterda boshqa, shuning uchun quyidagi blok yo'lning o'zini emas, munosabatlarni tekshiradi:

js
import { dirname } from "node:path";
import { fileURLToPath } from "node:url";

const { filename, dirname: dir, url } = import.meta;
console.log(filename.endsWith(".mjs"));
console.log(dir === dirname(filename));
console.log(fileURLToPath(url) === filename);
console.log(url.startsWith("file:///"));

Konsolda:

text
true
true
true
true

Eski kodda (Node 20.11 dan oldin) shu ishni qo'lda qilishgan: dirname(fileURLToPath(import.meta.url)). Bu satrni ko'p loyihalarda uchratasiz — u hali ham to'g'ri, faqat uzunroq.

Yana bir variant — faylni import.meta.url ga nisbatan URL bilan topish. valyuta aynan shu usulni ishlatadi: new URL("../fixtures/kurslar.json", import.meta.url). fs funksiyalari URL obyektini ham yo'l sifatida qabul qiladi.

Diqqat: process.cwd() va import.meta.dirname — boshqa-boshqa narsa. cwd — buyruq qayerdan ishga tushirilgani (terminalning joriy papkasi). dirname — fayl qayerda turgani. CLI'ni boshqa papkadan chaqirsangiz, cwd o'zgaradi, dirname esa yo'q. Dastur ichidagi fayllarni (masalan fixture) doim dirname yoki import.meta.url ga nisbatan toping. process.cwd() ni process obyekti darsida ko'rasiz.

Tekshirib ko'ring: valyuta ni C:/Users/…/loyihalar papkasidan node valyuta/src/cli.ts deb ishga tushirdingiz. readFile("fixtures/kurslar.json") ishlaydimi?

Javob

Yo'q. Nisbiy yo'l process.cwd() ga nisbatan hisoblanadi — C:/Users/…/loyihalar/fixtures/kurslar.json qidiriladi, u yerda esa fayl yo'q (ENOENT). To'g'ri yo'l — new URL("../fixtures/kurslar.json", import.meta.url): u cli.ts turgan joyga nisbatan.

5. Bir xil nom — har xil xulq

Ba'zi globallar ikkala muhitda bor, lekin biroz boshqacha ishlaydi. Uchtasini bilish foydali.

5.1 Taymerlar obyekt qaytaradi

Brauzerda setTimeout son (identifikator) qaytaradi. Node'da esa Timeout obyektini:

js
const timer = setTimeout(() => {}, 0);
console.log(typeof timer, timer.constructor.name);
console.log(typeof timer.unref, typeof timer.hasRef);
clearTimeout(timer);

const imm = setImmediate(() => {});
console.log(imm.constructor.name);
clearImmediate(imm);

Konsolda:

text
object Timeout
function function
Immediate

Obyektda foydali metodlar bor. Eng muhimi — unref(): "bu taymer jarayonni tirik ushlab turmasin". Node jarayoni loop'da kutadigan hech narsa qolmaganda tugaydi. Faol taymer esa jarayonni ushlab turadi. Masalan, "5 soniyada javob bo'lmasa, ogohlantir" taymeri CLI'ni behuda 5 soniya kutdirmasligi uchun unref() qilinadi. Taymerlarni chuqur timers va timers/promises darsida ko'rasiz.

TypeScript'da bu farq tip bilan ko'rinadi: Node tiplarida setTimeout NodeJS.Timeout qaytaradi, brauzer tiplarida — number. Ikkala muhitga mos kodda ReturnType<typeof setTimeout> yoziladi.

5.2 structuredClone — chuqur nusxa

structuredClone brauzerda ham, Node'da ham bor va qiymatning chuqur nusxasini oladi. JSON orqali nusxadan farqi — Date, Map, Set saqlanadi:

js
const original = { sana: new Date(0), kodlar: new Set(["USD"]) };

const copy = structuredClone(original);
console.log(copy.sana instanceof Date, copy.kodlar.has("USD"));

const viaJson = JSON.parse(JSON.stringify(original));
console.log(viaJson);

try {
  structuredClone({ format() {} });
} catch (e) {
  console.log(e.name);
}

Konsolda:

text
true true
{ sana: '1970-01-01T00:00:00.000Z', kodlar: {} }
DataCloneError

JSON sanani matnga, Set ni bo'sh obyektga aylantirdi. structuredClone ikkalasini saqladi, lekin funksiyani nusxalay olmadi — DataCloneError. Bu algoritm brauzerda postMessage da ishlatiladi, Node'da esa worker'lar orasida xabar yuborishda (worker_threads).

5.3 localStorage — faqat bayroq bilan

Node 24 da localStorage sukut bo'yicha yo'q. Uni --experimental-webstorage bayrog'i yoqadi va ma'lumot faylga saqlanadi. Node 24 hujjatida bu API "release candidate" (deyarli tayyor, lekin hali barqaror emas) deb belgilangan — 2026-10 holatiga. Biz ishga tushirdik (Node 24.21.0, Git Bash; qator oxiridagi \ buyruqni keyingi qatorda davom ettiradi):

bash
node --experimental-webstorage --localstorage-file=saqlash.db \
  -e "localStorage.setItem('kurs', '11903.15');
      console.log(localStorage.getItem('kurs'))"
text
11903.15
(node:18112) ExperimentalWarning: Web Storage is an experimental feature and might change at any time

Fayl ko'rsatilmasa, localStorage ga murojaatning o'zi xato beradi: TypeError [ERR_INVALID_ARG_VALUE]: The argument '--localstorage-file' is an invalid localStorage location. Received '' ("bunday localStorage joyi yaroqsiz, bo'sh qiymat berildi"). Xulosa: Node'da sozlama yoki kesh saqlash uchun localStorage ga emas, oddiy faylga tayaning. valyuta keshi aynan fayl bo'ladi (fs: uch API shakli).

6. Ikki muhitga mos kod

Ba'zan bitta modul ham brauzerda, ham Node'da ishlashi kerak (masalan, valyuta ning konvertatsiya funksiyalari). Qoidalar:

  1. Faqat umumiy qatlamga tayaning. fetch, URL, TextEncoder, crypto.subtle, structuredClone — ikkalasida bor. Buffer o'rniga Uint8Array va TextEncoder.
  2. Global obyektga globalThis orqali murojaat qiling, window yoki global orqali emas.
  3. Muhitni tekshirish kerak bo'lsa — xususiyatni tekshiring, nomni emas: typeof process !== "undefined" && process.versions?.node. Bun va Deno ham process ni qisman taqlid qiladi, shuning uchun versions.node ga qarang.
  4. Node moduliga shartli kirish uchun Node 22.3+ da process.getBuiltinModule("node:os") bor. U import siz, sinxron ravishda ichki modulni beradi. Brauzerda process yo'q — demak bu chaqiruv faqat Node tarmog'ida bo'ladi.
js
function runtimeName() {
  if (typeof process !== "undefined" && process.versions?.node) {
    const os = process.getBuiltinModule("node:os");
    const major = process.versions.node.split(".")[0];
    return `Node ${major} (${typeof os.cpus})`;
  }
  return typeof window !== "undefined" ? "brauzer" : "noma'lum";
}
console.log(runtimeName());

Konsolda:

text
Node 24 (function)

7. CLI qadami: holat yo'q

Bu darsda valyuta ga kod qo'shilmaydi. Lekin keyingi darsda boshlanadigan loyihaning ikkita qarori aynan shu darsdan kelib chiqadi (kanon holat 08 da ko'rasiz):

  • Loyiha boshidan ESM ("type": "module"). Shuning uchun unda __dirname yo'q — fixture fayli new URL("../fixtures/kurslar-2026-10-23.json", import.meta.url) bilan topiladi.
  • Faqat umumiy globallar — kurs modeli (kurs.ts) process, Buffer, fs ni ishlatmaydi. U toza funksiyalar to'plami: brauzerda ham ishlay oladi. Node'ga xos qism (fetch va fayl o'qish) alohida manba.ts da.

Kanon tajribasidagi to'liq ro'yxat (28 nom) — «O'lchov: Node 24 da nima bor» bo'limidagi blokning kengaytmasi; qo'shimcha topilgan: Blob, ReadableStream, EventTarget, queueMicrotask — bor; self, module — yo'q.

8. Ko'p uchraydigan xatolar

Xato Sabab Davosi
ReferenceError: window is not defined brauzer kodi Node'da globalThis yoki shart bilan
ReferenceError: __dirname is not defined in ES module scope ESM faylda CommonJS nomi import.meta.dirname
ReferenceError: require is not defined in ES module scope, you can use import instead ESM'da require import; majbur bo'lsangiz createRequire (CJS va ESM birga)
ReferenceError: localStorage is not defined Node'da Web Storage yo'q fayl yoki ma'lumotlar bazasi
ENOENT nisbiy yo'lda yo'l cwd ga nisbatan import.meta.url / dirname ga nisbatan
Type 'Timeout' is not assignable to type 'number' (TS) Node taymeri obyekt ReturnType<typeof setTimeout>

9. Mashqlar

Mashqlar kurs/mashqlar/24/07-global/ da.

1-mashq (oson): bor yoki yo'q

Node 24, ESM fayl (.mjs). typeof natijasini yozing:

  • typeof Buffer —
  • typeof document —
  • typeof structuredClone —
  • typeof __filename —
  • typeof navigator —
Yechim
  • function — Buffer — Node'ning binar ma'lumot klassi (Buffer).
  • undefined — document — brauzer sahifasi, Node'da sahifa yo'q.
  • function — umumiy veb API.
  • undefined — ESM'da yo'q; .cjs faylda "string" bo'lardi.
  • object — Node 21 dan beri global, lekin cheklangan.

2-mashq (o'rta): globallar hisoboti

.mjs fayl yozing: berilgan nomlar ro'yxatini uch guruhga ajratsin — umumiy (Node'da bor va brauzerda ham bo'lishi kutiladi), faqat Node, yo'q. "Faqat Node" ro'yxati qo'lda beriladi: ["process", "Buffer", "global", "setImmediate"]. Tekshiriladigan nomlar: fetch, process, window, URL, Buffer, alert, setImmediate, TextEncoder. Har guruhni bitta qatorda chiqaring.

Yechim
js
const nodeOnly = ["process", "Buffer", "global", "setImmediate"];
const names = ["fetch", "process", "window", "URL",
  "Buffer", "alert", "setImmediate", "TextEncoder"];

const groups = { umumiy: [], "faqat Node": [], "yo'q": [] };
for (const name of names) {
  const missing = typeof globalThis[name] === "undefined";
  if (missing) groups["yo'q"].push(name);
  else if (nodeOnly.includes(name)) groups["faqat Node"].push(name);
  else groups.umumiy.push(name);
}
for (const [group, list] of Object.entries(groups)) {
  console.log(`${group}: ${list.join(", ")}`);
}

Konsolda:

text
umumiy: fetch, URL, TextEncoder
faqat Node: process, Buffer, setImmediate
yo'q: window, alert

globalThis[name] — nomni satr sifatida tekshirish usuli. To'g'ridan typeof window ham ishlaydi, lekin ro'yxat bo'ylab yurganda nom o'zgaruvchida bo'ladi. Mavjud bo'lmagan nomni typeof bilan tekshirish xato bermaydi — undefined qaytaradi.

3-mashq (qiyin): CommonJS'dan ESM'ga

Quyidagi eski CommonJS kodni ESM'ga o'tkazing. Fayl o'zi turgan papkadagi kurs.json ni o'qiydi. Yechimingizni sinash uchun avval faylni o'zingiz yarating (kod ichida writeFileSync bilan), keyin o'qing va USD 11903.15 chiqaring. __dirname ham, process.cwd() ham ishlatilmasin.

js
const fs = require("fs");
const path = require("path");
const file = path.join(__dirname, "kurs.json");
const data = JSON.parse(fs.readFileSync(file, "utf8"));
console.log(data.Ccy, data.Rate);
Yechim
js
import { readFileSync, writeFileSync } from "node:fs";

const file = new URL("./kurs.json", import.meta.url);
writeFileSync(file, JSON.stringify({ Ccy: "USD", Rate: "11903.15" }));

const data = JSON.parse(readFileSync(file, "utf8"));
console.log(data.Ccy, data.Rate);

Konsolda:

text
USD 11903.15

new URL("./kurs.json", import.meta.url) — joriy faylga nisbatan manzil. readFileSync va writeFileSync URL obyektini to'g'ridan qabul qiladi. Ikkinchi yo'l: join(import.meta.dirname, "kurs.json") — natija bir xil. process.cwd() bilan esa dastur boshqa papkadan chaqirilganda fayl topilmasdi.

10. Real ishda

  • Izomorf kutubxonalar — zod, date-fns, nanoid kabi paketlar ham brauzerda, ham Node'da ishlaydi. Ular faqat umumiy qatlamga tayanadi va package.json dagi exports shartlari bilan muhitga mos faylni beradi (package.json IV: kirish nuqtalari).
  • SSR xatolari — Next.js da window is not defined — eng ko'p uchraydigan hydration'dan oldingi xato: komponent serverda (Node'da) ham chiziladi.
  • Eski kod migratsiyasi — CommonJS'dan ESM'ga o'tishda __dirname → import.meta.dirname almashtirish birinchi qadam bo'ladi.
  • Intervyu savoli: "globalThis nima uchun kerak?" — har muhitda bitta nom bilan global obyektga murojaat qilish uchun (window, self, global o'rniga).

Xulosa

  • Global — import siz ishlatiladigan nom; uning ro'yxati muhitga bog'liq.
  • Node'da window, document, localStorage yo'q; process, Buffer, setImmediate — faqat Node'da.
  • Node 24 da veb API'lar global: fetch, URL, URLPattern, AbortController, structuredClone, crypto, navigator (cheklangan).
  • globalThis — hamma muhitda global obyekt; global — Node'dagi eski nom.
  • ESM'da __dirname yo'q → import.meta.dirname, import.meta.filename yoki new URL(…, import.meta.url).
  • Taymerlar Node'da obyekt (unref() bor), brauzerda son.

Keyingi dars: process obyekti: argv, env, exit kodlari va signallar — valyuta loyihasi shu darsda boshlanadi.

Manbalar

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
Node.js global obyektlari: globalThis, process, Buffer va brauzer farqi — IlmHamroh