IlmHamroh
JavaScript Full-stack/12-qism. JavaScript: ilg'or mavzular va kod sifati41/44-dars21 daqiqa
Mundarija (38)

JS versiyalari va brauzer mosligi: ES2015 dan ES2027 gacha, Baseline va polyfill

Qisqacha: JavaScript tili ECMAScript standarti bilan belgilanadi va har yili iyunda yangi nashr chiqadi: ES2026 — 2026-yil 30-iyunda tasdiqlandi. Yangi imkoniyat standartga kirishdan oldin TC39 qo'mitasida 0 dan 4 gacha bosqichdan o'tadi. Lekin standartda borligi — brauzerda borligi degani emas. Tekshirish: Baseline belgisi (web-features), caniuse.com, MDN jadvali. Yo'q bo'lsa: yetishmayotgan funksiyani polyfill qo'shadi (core-js), yangi sintaksisni esa transpiler eski sintaksisga aylantiradi (Babel, SWC). Qaysi brauzerlar uchun — browserslist aytadi.

Bu darsda

  • JavaScript, ECMAScript, ES6 va ES2015 nomlari farqini va har yilgi nashr qanday chiqishini tushuntira olasiz.
  • TC39 bosqichlari (0, 1, 2, 2.7, 3, 4) nima ekanini va qaysi bosqichdagi imkoniyatni ishlatish xavfsizligini bilasiz.
  • Imkoniyat qaysi brauzerlarda borligini Baseline, caniuse va MDN orqali tekshirasiz.
  • Kodda imkoniyat bor-yo'qligini tekshirasiz (feature detection) va o'zingiz kichik polyfill yozasiz.
  • Polyfill va transpile farqini, core-js, Babel, SWC va browserslist vazifasini haqiqiy chiqishlarda ko'rasiz.

Oldin bilishingiz kerak: Veb standartlari va brauzer mosligi, Brauzer mosligi: Baseline, caniuse va @supports, npm ga birinchi qadam, Xususiyat deskriptorlari, O'rnatilgan prototiplar va wrapper obyektlar, JavaScript'ning mashhur tuzoqlari.

1. Nega bu kerak?

Sardor vazifalar dagi teglarni sanaydigan qatorni chiroyliroq yozmoqchi edi. Hozir u shunday:

js
sanoq.set(teg, (sanoq.get(teg) ?? 0) + 1);

U ES2026 da yangi Map.prototype.getOrInsert metodi borligini o'qidi: "kalit bo'lsa — qiymatini qaytaradi, yo'q bo'lsa — qo'shib, keyin qaytaradi". Chrome'da sinab ko'rdi — ishladi. Keyin npm test ni ishga tushirdi:

text
TypeError: sanoq.getOrInsert is not a function

Tarjimasi: "sanoq.getOrInsert — funksiya emas". Chrome 154 da metod bor, Node 24 da esa yo'q. Testlar Node'da ishlaydi — demak, yiqildi.

Bu birinchi holat emas. Promise yordamchilari darsida Promise.try Node 22 da yo'qligini ko'rgan edik. Lookahead va lookbehind darsida esa bitta (?<=...) eski iPhone'larda butun saytni sindirganini o'qigansiz.

Bu darsda uchta savolga javob beramiz. Yangi imkoniyat qayerdan keladi? Qaysi brauzerda borligini qanday bilaman? Yo'q bo'lsa nima qilaman?

2. JavaScript va ECMAScript

2.1 Til va standart

ECMAScript — JavaScript tilining rasmiy standarti, ya'ni "til qanday ishlashi kerak"ligini yozib qo'ygan hujjat. Uning raqami — ECMA-262, uni Ecma International tashkiloti nashr qiladi. JavaScript — shu standartning brauzerlar va Node'dagi amalga oshirilishi (implementation): standartda yozilgan qoidani o'z dvigatelida haqiqatan dastur qilib yozib chiqish. Chrome va Node'da bu ishni V8 dvigateli qiladi, Firefox'da — SpiderMonkey, Safari'da — JavaScriptCore.

O'xshatish: futbol qoidalari kitobi va har bir stadiondagi o'yin. Qoidalar bitta, stadionlar ko'p. Hamma stadion yangi qoidani bir kunda qabul qilmaydi.

Standartni TC39 qo'mitasi yozadi. Unda brauzer kompaniyalari (Google, Apple, Mozilla, Microsoft), boshqa kompaniyalar va mustaqil mutaxassislar bor. Ularning yig'ilishlari ochiq: qaydlari GitHub'da e'lon qilinadi.

2.2 ES6 va ES2015 — bitta narsa

Uzoq vaqt nashrlar raqam bilan atalgan: ES3 (1999), ES5 (2009). ES4 umuman chiqmagan — kelishuvga erisha olishmagan. 2015-yilda katta oltinchi nashr chiqdi: let, const, arrow funksiyalar, klasslar, modullar, Promise. Uni ES6 deb ham, ES2015 deb ham atashadi.

Shundan keyin TC39 tartibni o'zgartirdi: katta nashr o'rniga har yili kichik nashr. Nomi — yil bilan: ES2016, ES2017 … ES2026. Shu tartibda o'n bitta nashr chiqdi. Eski maqolalarda "ES7", "ES8" ni ko'rsangiz: ES7 = ES2016, ES8 = ES2017 (raqam + 2009).

Har nashr Ecma'ning bosh assambleyasida iyun oyida tasdiqlanadi. ES2025 — 2025-yil 25-iyunda, ES2026 — 2026-yil 30-iyunda (Ecma'ning 131-assambleyasi, Jeneva).

2.3 Xronologiya: kursda nima qayerdan kelgan

Nashr Asosiy imkoniyatlar Kursda
ES2015 let/const, arrow, klass, modul, Promise, Map/Set 08–11
ES2016 includes, ** 08
ES2017 async/await, Object.entries, padStart 08, 11
ES2018 obyekt spread, for await, finally, lookbehind, \p{…} 08, 11, 12
ES2019 flat/flatMap, Object.fromEntries, barqaror sort 10
ES2020 ??, ?., BigInt, globalThis, import(), allSettled 08, 10, 11
ES2021 ??=, replaceAll, Promise.any, WeakRef, 1_000 08, 10, 11
ES2022 top-level await, #private, at(), Object.hasOwn, cause 10, 11
ES2023 toSorted, with, findLast 10
ES2024 Object.groupBy, withResolvers, v flag 10, 11, 12
ES2025 Set metodlari, iterator helpers, Promise.try, RegExp.escape, JSON modullar 10, 11, 12
ES2026 getOrInsert, Math.sumPrecise, base64, Iterator.concat, Error.isError, Array.fromAsync shu dars
ES2027 Temporal, using, iterator chunks/zip — hali loyiha 10, 12

Jadval TC39'ning rasmiy ro'yxatidan olingan (tc39/proposals, "Finished Proposals", 2026-10-05). E'tibor bering: using va Temporal — ES2027 da. Ular 4-bosqichga yetgan, lekin nashr 2027-yil iyunida tasdiqlanadi.

Har nashr qanchalik "katta" bo'lgani — quyidagi grafikda. Har yili tugallangan takliflar soni:

ECMAScript nashriga kirgan takliflar soni
Takliflar, ta
1022 0162 027Nashr, yil4-bosqichga yetganlar: 2 016 yil → 2 ta4-bosqichga yetganlar: 2 017 yil → 6 ta4-bosqichga yetganlar: 2 018 yil → 8 ta4-bosqichga yetganlar: 2 019 yil → 8 ta4-bosqichga yetganlar: 2 020 yil → 9 ta4-bosqichga yetganlar: 2 021 yil → 5 ta4-bosqichga yetganlar: 2 022 yil → 7 ta4-bosqichga yetganlar: 2 023 yil → 4 ta4-bosqichga yetganlar: 2 024 yil → 7 ta4-bosqichga yetganlar: 2 025 yil → 10 ta4-bosqichga yetganlar: 2 026 yil → 7 ta4-bosqichga yetganlar: 2 027 yil → 7 ta
ECMAScript nashriga kirgan takliflar soni
Nashr4-bosqichga yetganlar
2 0162
2 0176
2 0188
2 0198
2 0209
2 0215
2 0227
2 0234
2 0247
2 02510
2 0267
2 0277

Manba: github.com/tc39/proposals — finished-proposals.md, 2026-10-05 holati; ES2027 — hozircha (nashr 2027-yil iyunida)

Nimaga qarang: nashrlar kichik va tekis — yiliga 4–10 ta imkoniyat. Bu ES2015 dagi "hammasi birdaniga" o'rniga tanlangan yo'l: brauzerlar yangilikni bosqichma-bosqich qo'shadi.

Tekshirib ko'ring: Maqolada "ES8 dagi async/await" deb yozilgan. Bu qaysi yil nashri?

Javob

ES2017. Raqamli nom + 2009 = yil: 8 + 2009 = 2017. Jadvalda ham async/await — ES2017.

3. TC39 bosqichlari

3.1 Taklifning yo'li

Har yangi imkoniyat taklif (proposal) sifatida boshlanadi va bosqichma-bosqich ko'tariladi:

flowchart LR
  S0["0: g'oya"] --> S1["1: muammo va yechim"]
  S1 --> S2["2: qoralama"]
  S2 --> S27["2.7: to'liq matn, testlar"]
  S27 --> S3["3: brauzerlar qo'shmoqda"]
  S3 --> S4["4: tugadi"]
  S4 --> N["Iyundagi nashr"]
  • 0-bosqich — g'oya. Hech qanday majburiyat yo'q.
  • 1-bosqich — muammo aniq yozilgan, taklifni olib boradigan mas'ul shaxs (champion — "himoyachi") bor, yechim izlanmoqda.
  • 2-bosqich — qoralama: sintaksis va API tasvirlangan, misollar bor. Hali ko'p narsa o'zgarishi mumkin.
  • 2.7-bosqich — keyinroq qo'shilgan oraliq qadam: standartga kiradigan matn (spetsifikatsiya) to'liq, tekshiruvchilar rozi. Endi rasmiy testlar yoziladi — ular Test262 deb ataladigan umumiy to'plamga qo'shiladi va har dvigatel o'zini shu testlar bilan tekshiradi.
  • 3-bosqich — brauzerlar qo'shishni boshlaydi. Faqat amalda topilgan muammolar tufayli o'zgaradi.
  • 4-bosqich — tugadi. Shart: kamida ikki mustaqil amalga oshirish testlardan o'tgan va amalda sinalgan. Keyingi iyundagi nashrga kiradi.

3.2 Qaysi bosqichdagini ishlatish mumkin?

Qoida oddiy:

  • 4-bosqich — bemalol, lekin brauzerda borligini tekshirib (keyingi bo'lim).
  • 3-bosqich — polyfill bilan, ehtiyotkorlik bilan. Masalan, Temporal uzoq vaqt 3-bosqichda turdi va shu davrda polyfill orqali ishlatildi.
  • 0–2-bosqich — o'quv tajribasi uchun. Ishchi kodda — yo'q: taklif o'zgarishi yoki butunlay bekor bo'lishi mumkin. Masalan, Records & Tuples taklifi 2025-yilda qaytarib olindi (Immutability chuqur).

Barcha takliflar va ularning bosqichi — github.com/tc39/proposals da.

Tekshirib ko'ring: Blogda "yangi pipeline operatori |> — 2-bosqichda" deb yozilgan. Uni vazifalar da ishlatasizmi?

Javob

Yo'q. 2-bosqich — qoralama: sintaksis hali o'zgarishi mumkin, hech bir brauzer uni standart holatda qo'llamaydi. Uni faqat transpiler orqali va tajriba sifatida sinash mumkin. Ishchi loyihada — 4-bosqich va brauzerlarda borligi tekshirilgan imkoniyatlar.

4. Brauzerda bormi? Baseline, caniuse va MDN

4.1 Baseline

Veb standartlari va brauzer mosligi darsida Baseline belgisi bilan tanishgan edik. Eslatib o'tamiz: u "bu imkoniyat asosiy brauzerlarning hammasida ishlaydimi?" savoliga bitta belgi bilan javob beradi. Uni W3C'dagi WebDX guruhi (brauzer kompaniyalari vakillari) yuritadi. Asosiy brauzerlar: Chrome, Edge, Firefox va Safari — kompyuterda va telefonda.

Uch holat bor:

Holat Ma'nosi Ishlatish
Limited availability kamida bitta asosiy brauzerda yo'q polyfill yoki zaxira yo'l bilan
Newly available oxirgi brauzer ham qo'shdi yangi brauzerli auditoriyaga
Widely available "yangi" bo'lganiga 30 oy o'tdi bemalol

Shu belgini MDN sahifalarining tepasida ko'rasiz (masalan, Object.groupBy sahifasida). Uning ma'lumotlari web-features npm paketida ochiq. Biz shu darsda 3.40.1 versiyasini ishlatdik (npm view web-features version, 2026-10-05):

js
// baseline.mjs — avval: npm i web-features@3.40.1
import { features } from "web-features";

for (const id of ["array-group", "set-methods", "getorinsert"]) {
  const { name, status } = features[id];
  console.log(name, status.baseline, status.baseline_low_date);
}

Haqiqiy chiqish (Node 24.21):

text
Array grouping high 2024-03-05
Set methods low 2024-06-11
Map getOrInsert() low 2026-02-14

high — Widely available, low — Newly available, false — Limited. Object.groupBy 2024-yil 5-martdan hamma asosiy brauzerda bor va 2026-yil sentabrdan "keng tarqalgan". getOrInsert esa 2026-yil fevralidan "yangi". Temporal — false: Safari'da hali yo'q (Temporal API darsida ko'rgan edik).

4.2 caniuse.com va MDN jadvali

  • caniuse.com — imkoniyat nomini yozasiz, har brauzer versiyasi bo'yicha jadval chiqadi. Foydasi: "dunyodagi foydalanuvchilarning necha foizida ishlaydi" raqami (StatCounter ma'lumoti asosida).
  • MDN — har metod sahifasining pastida "Browser compatibility" jadvali. Unda Node.js va Deno ham bor — server kodi uchun foydali.

Ikkalasi ham bir manbadan foydalanadi: brauzerlar mosligi ma'lumotlar bazasi (@mdn/browser-compat-data). Shuning uchun raqamlari odatda bir xil.

4.3 Node.js alohida

Node'da brauzer yo'q, lekin xuddi shu savol bor: Node qaysi V8 versiyasini ishlatadi? Node 24.21 da V8 13.6. Unda ES2026 ning bir qismi bor, bir qismi yo'q:

js
console.log(typeof Promise.try); // function
console.log(typeof RegExp.escape); // function
console.log(typeof Map.prototype.getOrInsert); // undefined
console.log(typeof Math.sumPrecise); // undefined

Chrome 154 da to'rttasi ham function. Loyiha qaysi Node versiyasida ishlashini package.json dagi engines maydonida yozib qo'yish odat: "engines": { "node": ">=24" }.

5. Kodda tekshirish: feature detection

5.1 Metod bormi?

Feature detection (imkoniyatni aniqlash) — kodning o'zi "bu imkoniyat shu yerda bormi?" deb tekshiradi va shunga qarab yo'l tanlaydi. Brauzer nomini emas, imkoniyatning o'zini tekshiramiz.

js
const counts = new Map([["#bozor", 1]]);

function increment(tag) {
  if (typeof counts.getOrInsert === "function") {
    counts.set(tag, counts.getOrInsert(tag, 0) + 1);
  } else {
    counts.set(tag, (counts.get(tag) ?? 0) + 1);
  }
}

increment("#bozor");
increment("#uy");
console.log(counts); // Map(2) { '#bozor' => 2, '#uy' => 1 }

Natija Node 24 da ham (ikkinchi yo'l), Chrome 154 da ham (birinchi yo'l) bir xil. Boshqa shakllari: "groupBy" in Object, "BroadcastChannel" in globalThis.

5.2 Sintaksisni bunday tekshirib bo'lmaydi

Metod yo'q bo'lsa — undefined, uni tekshirsa bo'ladi. Yangi sintaksis esa boshqacha. Brauzer tanimagan sintaksisni ko'rsa, butun faylni o'qishdan bosh tortadi — SyntaxError. Fayldagi if ga navbat ham kelmaydi. Lookbehind'li regex eski Safari'da saytni aynan shunday sindirgan.

Chiqish yo'li — sintaksisni satr ichida, try bilan sinash:

js
function supportsLookbehind() {
  try {
    new RegExp("(?<=#)\\p{L}+", "u");
    return true;
  } catch {
    return false;
  }
}
console.log(supportsLookbehind()); // true

new RegExp naqshni ishlash paytida o'qiydi, shuning uchun xato catch ga tushadi. Lekin ?., ??, #private kabi tilning o'z sintaksisini bunday sinash noqulay. Ular uchun boshqa yechim bor — transpile («Transpile» bo'limi).

Tekshirib ko'ring: Nega if (typeof Temporal !== "undefined") ishlaydi, if (brauzer === "Safari") esa yomon g'oya?

Javob

Birinchisi imkoniyatning o'zini tekshiradi: Safari ertaga Temporal'ni qo'shsa, kod o'zi yangi yo'lga o'tadi. Ikkinchisi brauzer nomiga bog'langan: Safari yangilangach ham eski yo'lda qoladi, boshqa "Temporal'siz" brauzerni esa umuman bilmaydi. Brauzer nomi (navigator.userAgent) ishonchsiz ham — uni o'zgartirish oson.

6. Polyfill

6.1 O'zimiz yozamiz

Polyfill — yetishmayotgan funksiya yoki metodni eski muhitga JavaScript bilan qo'shib qo'yadigan kod. Nomi — devordagi yoriqni to'ldiradigan qurilish shpaklyovkasidan (inglizcha "Polyfilla" brendi). Qoidasi: avval tekshir, yo'q bo'lsagina qo'sh.

js
if (typeof Map.prototype.getOrInsert !== "function") {
  Object.defineProperty(Map.prototype, "getOrInsert", {
    value(key, defaultValue) {
      if (!this.has(key)) this.set(key, defaultValue);
      return this.get(key);
    },
    writable: true,
    configurable: true,
  });
}

const counts = new Map();
for (const tag of ["#bozor", "#uy", "#bozor"]) {
  counts.set(tag, counts.getOrInsert(tag, 0) + 1);
}
console.log(counts); // Map(2) { '#bozor' => 2, '#uy' => 1 }

Qator-qator:

  • if (typeof … !== "function") — metod bo'lsa, hech narsa qilmaymiz. Brauzerning o'z (tezroq va to'g'riroq) versiyasi ishlaydi.
  • Object.defineProperty — oddiy Map.prototype.getOrInsert = … emas. Sababi: oddiy tayinlash sanaladigan (enumerable) xususiyat yaratadi, o'rnatilgan metodlar esa sanalmaydi (Xususiyat deskriptorlari). enumerable ni yozmasak — false.
  • value(key, defaultValue) — metod. this — metod chaqirilgan Map.

6.2 Tayyor polyfill: core-js

Har metodni o'zingiz yozish xavfli: standartdagi chegaraviy holatlarni o'tkazib yuborish oson. Shuning uchun tayyor to'plam ishlatiladi. Eng mashhuri — core-js (shu dars yozilganda 3.50.0). U ES2027 gacha deyarli hamma narsani qoplaydi:

js
// core-js-sinov.mjs — avval: npm i core-js@3.50.0
console.log(typeof Map.prototype.getOrInsert);
await import("core-js/actual/map/get-or-insert.js");
console.log(typeof Map.prototype.getOrInsert);

Node 24.21 da haqiqiy chiqish:

text
undefined
function

Faqat kerakli metodni ulash mumkin (core-js/actual/map/get-or-insert.js) yoki hammasini (core-js/actual). Qo'lda tanlash shart emas — buni keyingi bo'limdagi vositalar avtomatik qiladi.

Ponyfill — polyfill'ning "yumshoq" varianti: global prototipga tegmaydi, oddiy funksiya sifatida import qilinadi (getOrInsert(counts, tag, 0)). Kutubxona yozsangiz — ponyfill ishlating: birovning sahifasidagi Map.prototype ni o'zgartirish sizning ishingiz emas.

6.3 Nega o'rnatilgan prototipni o'zingiz o'zgartirmaysiz

2018-yilda TC39 massivga flatten metodini qo'shmoqchi edi. Ma'lum bo'ldiki, eski MooTools kutubxonasi Array.prototype.flatten ni o'zicha, boshqacha qo'shgan ekan. Standart metod qo'shilsa, MooTools ishlatgan minglab eski saytlar sinardi. Natijada standartdagi nom o'zgartirildi — flat. Bu voqea "smooshgate" deb ataladi. 2014-yilda xuddi shu sabab bilan String.prototype.contains o'rniga includes tanlangan.

Saboq: o'rnatilgan prototipga faqat standartdagi metodni, standartdagi nom va xulq bilan, "yo'q bo'lsa" sharti bilan qo'shing. O'zingizning "foydali" metodingizni (Array.prototype.oxirgisi) — hech qachon.

Tekshirib ko'ring: Polyfill nega if (typeof … !== "function") sharti bilan boshlanadi? Shartsiz qo'shsak nima yo'qotamiz?

Javob

Brauzerda metod bor bo'lsa, uning o'z versiyasi ishlashi kerak: u tezroq va standartning hamma chegaraviy holatlarini to'g'ri bajaradi. Shartsiz qo'shsak, sizning sodda (ehtimol xatoli) versiyangiz uni bosib ketadi — yangi brauzerda ham. Polyfill faqat "yoriq" bor joyni to'ldiradi.

7. Transpile: yangi sintaksis — eski sintaksis

7.1 Polyfill nimani qila olmaydi

Polyfill — JavaScript kodi, u faqat yetishmayotgan qiymat yoki metod qo'sha oladi. ?. yoki ?? esa metod emas — tilning grammatikasi. Uni tanimaydigan brauzer faylni o'qiy olmaydi, polyfill'ga navbat kelmaydi.

Transpile (transpilyatsiya) — kodni bir xil darajadagi boshqa kodga o'girish. Bizda: yangi sintaksisli JavaScript'ni eski brauzer tushunadigan JavaScript'ga. Buni qiladigan dastur — transpiler: Babel (8.0.6) va SWC (1.16.13, Rust'da yozilgan, ancha tez).

7.2 Haqiqiy misol: Babel

Kirish fayli:

js
const phone = customer?.phone ?? "yo'q";
const byType = Object.groupBy(menu, (t) => t.type);

Babel sozlamasi (babel.config.json): nishon — Safari 13, polyfill'lar uchun babel-plugin-polyfill-corejs3 (1.0.0):

json
{
  "presets": [["@babel/preset-env", { "targets": "safari 13" }]],
  "plugins": [
    [
      "polyfill-corejs3",
      { "method": "usage-global", "version": "3.50" }
    ]
  ]
}

npx babel src/menu.js ning haqiqiy chiqishi (o'qish oson bo'lishi uchun Prettier bilan 60 belgiga formatladik):

js
var _customer$phone, _customer;
import "core-js/modules/es.object.group-by.js";
const phone =
  (_customer$phone =
    (_customer = customer) === null || _customer === void 0
      ? void 0
      : _customer.phone) !== null &&
  _customer$phone !== void 0
    ? _customer$phone
    : "yo'q";
const byType = Object.groupBy(menu, (t) => t.type);

Ikki xil ish bo'ldi, ikkalasi ham ko'rinib turibdi:

  1. Transpile: ?. va ?? g'oyib bo'ldi. O'rniga — === null || … === void 0 tekshiruvlari. void 0 — undefined ning eski, qisqa yozuvi.
  2. Polyfill: Object.groupBy qatori o'zgarmadi — bu metod, sintaksis emas. Uning o'rniga fayl boshiga core-js'dan faqat shu metod ulandi.

Nishonni "chrome 120" ga o'zgartirsak, ?. va ?? o'zgarmay qoladi — Chrome 120 ularni biladi. Transpiler faqat kerakli joyni o'zgartiradi.

Tekshirib ko'ring: Babel ?. ni o'zgartirdi, Object.groupBy qatorini esa yo'q. Nega?

Javob

?. — sintaksis: eski brauzer uni o'qiy olmaydi, shuning uchun uni eski yozuvga o'girish (transpile) kerak. Object.groupBy — oddiy metod chaqiruvi, eski brauzer bu qatorni o'qiy oladi, faqat metod yo'q. Uni polyfill hal qiladi — shuning uchun Babel fayl boshiga core-js'dan shu metodni uladi.

Diqqat: Babel 8 da @babel/preset-env ning eski useBuiltIns opsiyasi olib tashlangan. Eski maqoladagi sozlamani ko'chirsangiz, shunday xato chiqadi: The 'useBuiltIns' option has been removed. Please use babel-plugin-polyfill-corejs3 instead. — "useBuiltIns opsiyasi olib tashlandi, o'rniga babel-plugin-polyfill-corejs3 ishlating". Versiyaga bog'liq maslahat — eskiradigan maslahat.

Amalda Babel'ni o'zingiz kamdan-kam sozlaysiz: Vite kabi vositalar uni (yoki SWC'ni, yoki yana bir tez transpiler — esbuild'ni) ichida ishlatadi. Bu 16-qismda — Frontend asboblar zanjiri darsidan boshlab.

8. browserslist: "qaysi brauzerlar?" savoliga bitta javob

Babel ham, core-js plagini ham, CSS uchun Autoprefixer ham bir savolni so'raydi: "qaysi brauzerlarni qo'llaymiz?". Har biriga alohida yozmaslik uchun browserslist bor — bitta ro'yxat, hamma vosita o'qiydi. U package.json dagi "browserslist" maydonida yoki .browserslistrc faylida yoziladi.

Ro'yxat so'rov bilan yoziladi. Ularni terminalda sinash mumkin (browserslist 4.29.3, caniuse-lite 1.0.30001814):

bash
npx browserslist --coverage "defaults"
text
These browsers account for 84.65% of all users globally

Tarjimasi: "bu brauzerlar dunyodagi barcha foydalanuvchilarning 84,65 foizini qamraydi". defaults — "0,5 foizdan ko'p ulushli, har birining oxirgi 2 versiyasi, Firefox ESR (korxonalar uchun uzoq qo'llab-quvvatlanadigan versiya), o'lik bo'lmaganlar". "O'lik" — 24 oydan beri yangilanmagan brauzer. Ro'yxatning o'zi (npx browserslist "defaults") — 35 qator, boshi:

text
and_chr 154
and_ff 157
and_qq 14.9
and_uc 15.5
android 154
chrome 154
chrome 153

Yana bir foydali so'rov — Baseline bilan: "baseline widely available". U Safari'ni 17.4 gacha, Chrome'ni 123 gacha qamraydi (jami 134 qator) — ya'ni "Widely available" imkoniyatlar ishlaydigan brauzerlar. Uni batafsil Polyfill, browserslist va Baseline darsida ko'ramiz.

flowchart TD
  B["browserslist: qaysi brauzerlar"] --> T["Babel / SWC: sintaksisni o'giradi"]
  B --> P["core-js plagini: kerakli polyfill"]
  B --> C["Autoprefixer: CSS prefikslari"]
  T --> F["Eski brauzer ham o'qiy oladigan fayl"]
  P --> F

9. Hujumchi nigohi

Polyfill — saytingizda har bir mehmonning brauzerida ishlaydigan begona kod. Uni qayerdan olayotganingiz muhim.

Uzoq yillar ko'p saytlar polyfill'ni cdn.polyfill.io dan <script> bilan ulardi: xizmat brauzerga qarab kerakli polyfill'larni yuborardi. 2024-yil fevralida domen va loyiha yangi egaga — Funnull kompaniyasiga o'tdi. Iyun oyida Sansec xavfsizlik kompaniyasi xabar berdi: skript o'zgartirilgan va telefondagi mehmonlarni firibgar saytlarga yo'naltirmoqda. BleepingComputer ma'lumotiga ko'ra, 100 mingdan ortiq sayt zarar ko'rgan. Sayt egalari o'z kodida hech narsani o'zgartirmagan edi.

Himoya:

  • polyfill'ni npm'dan aniq versiya bilan o'rnating va o'z saytingizdan bering (bundler orqali), begona CDN'dan emas;
  • begona CDN'dan skript ulasangiz — integrity atributi (SRI — Subresource Integrity, "yuklangan fayl butunligi") bilan: fayl bir bayt o'zgarsa ham brauzer uni ishlatmaydi;
  • kerak bo'lmagan polyfill'ni olib tashlang: bugun Baseline "Widely available" bo'lgan imkoniyat uchun polyfill — ortiqcha kod va ortiqcha xavf.

10. Ko'p uchraydigan xatolar

10.1 "Chrome'da ishlayapti — demak, hammada ishlaydi"

Yangi metodni faqat o'z brauzeringizda sinash. Testlar Node'da, mehmonlarning yarmi Safari'da.

MDN/Baseline'ni tekshiring, npm test ni ishga tushiring.

10.2 Sintaksisni if bilan "himoyalash"

if (yangiBrauzer) { const x = a ?? b; } — eski brauzer faylni umuman o'qiy olmaydi.

Sintaksis uchun — transpile; metod uchun — feature detection yoki polyfill.

10.3 2-bosqichdagi taklifni ishchi kodda ishlatish

Blogda ko'rgan yangi sintaksisni Babel plagini bilan darhol loyihaga qo'shish.

4-bosqich va Baseline. Undan oldingisi — tajriba uchun alohida papkada.

10.4 Polyfill'ni shartsiz qo'shish

Map.prototype.getOrInsert = function … — brauzerning o'z versiyasini sizning (ehtimol xatoli) versiyangiz bosib ketadi.

if (typeof … !== "function") va Object.defineProperty.

11. Mashqlar

1-mashq (oson): Nashr va bosqich

Javob bering:

  1. toSorted qaysi nashrda kelgan?
  2. Kamida nechta mustaqil amalga oshirish bo'lganda taklif 4-bosqichga o'tadi?
  3. Baseline "Widely available" bo'lishi uchun "Newly available" dan keyin necha oy o'tishi kerak?
Yechim
  1. ES2023 — "nusxa bilan o'zgartirish" metodlari (toSorted, toReversed, with) shu yili kelgan.
  2. Ikkita — ikki xil dvigatelda testlardan o'tgan va amalda sinalgan.
  3. 30 oy. Shu vaqt ichida ko'p foydalanuvchilar brauzerini yangilab ulguradi.

2-mashq (o'rta): Math.sumPrecise polyfill'i

Math.sumPrecise (ES2026) sonlar ro'yxatini yaxlitlash xatosisiz qo'shadi. Node 24 da u yo'q. Sodda polyfill yozing: yo'q bo'lsagina qo'shilsin, ichida oddiy reduce ishlatilsin (aniq algoritm emas — faqat shakl uchun). Keyin Math.sumPrecise([35000, 28000, 5000]) ni chiqaring. Ishora: «O'zimiz yozamiz» bo'limidagi Object.defineProperty; Math — oddiy obyekt.

Yechim
js
if (typeof Math.sumPrecise !== "function") {
  Object.defineProperty(Math, "sumPrecise", {
    value(numbers) {
      return [...numbers].reduce((sum, n) => sum + n, -0);
    },
    writable: true,
    configurable: true,
  });
}
console.log(Math.sumPrecise([35000, 28000, 5000])); // 68000

-0 dan boshlaganimiz — standartdagi kichik detal: bo'sh ro'yxat yig'indisi -0. Bu polyfill aniq emas: Math.sumPrecise([1e20, 0.1, -1e20]) haqiqiy metodda 0.1, bizda esa 0. Shuning uchun ishchi kodda o'zingiz yozgan "o'xshash" polyfill emas — core-js (core-js/actual/math/sum-precise.js).

3-mashq (qiyin): Sintaksis va metod

Quyidagi kod Safari 13 da ishlashi kerak. Har qatorda nima kerak: transpile, polyfill yoki hech narsa? Javobni jadval qilib yozing, keyin web-features yoki MDN'dan tekshiring.

js
const note = booking?.note ?? "";
const tags = note.match(/#\p{L}+/gu) ?? [];
const last = tags.at(-1);
const copy = structuredClone(booking);
Yechim
Qator Nima Nega
?., ?? transpile ES2020 sintaksisi, Safari 13.1 dan
\p{L} + u hech narsa ES2018, Safari 11.1 dan bor
at(-1) polyfill ES2022 metodi, Safari 15.4 dan
structuredClone polyfill brauzer API'si, Safari 15.4 dan

structuredClone — ECMAScript emas, HTML standartidagi brauzer API'si. core-js uni ham qoplaydi (core-js/actual/structured-clone.js), lekin barcha holatlarni emas. Muhim saboq: "polyfill bilan hal bo'ladimi?" savoli "bu metodmi yoki sintaksismi?" savoliga bog'liq.

4-mashq: Vazifalar qadami — qaysi brauzerlarda ishlaydi?

vazifalar README'sida "qo'llab-quvvatlanadigan brauzerlar" yo'q. Uni o'lchab topamiz. kurs/mashqlar/12/41-moslik/ da npm init -y qiling, package.json ga "type": "module" qo'shing, npm i web-features@3.40.1 va moslik.mjs ni yozing. U vazifalar ishlatadigan oltita imkoniyatni (toSorted, Object.groupBy, Set.prototype.difference, AbortSignal.any, AbortSignal.timeout, BroadcastChannel) tekshirib, har brauzer uchun eng katta talab qilinadigan versiyani chiqarsin. Ishora: «Baseline» bo'limidagi kod; web-features id'lari — array-by-copy, array-group, set-methods, abortsignal-any, abortsignal-timeout, broadcast-channel.

Yechim
js
// moslik.mjs — vazifalar ishlatadigan imkoniyatlar qayerda bor?
import { features } from "web-features";

const FEATURES = [
  "array-by-copy", // toSorted
  "array-group", // Object.groupBy
  "set-methods", // Set.prototype.difference
  "abortsignal-any", // AbortSignal.any
  "abortsignal-timeout", // AbortSignal.timeout
  "broadcast-channel", // BroadcastChannel
];
const BROWSERS = ["chrome", "firefox", "safari"];
const minimum = { chrome: "0", firefox: "0", safari: "0" };

for (const id of FEATURES) {
  const { name, status } = features[id];
  const cells = BROWSERS.map((b) => `${b} ${status.support[b]}`);
  console.log(`${name}: ${status.baseline} | ${cells.join(", ")}`);
  for (const b of BROWSERS) {
    const v = status.support[b];
    if (parseFloat(v) > parseFloat(minimum[b])) minimum[b] = v;
  }
}
console.log("Eng kichik talab:", minimum);

Haqiqiy chiqish (web-features 3.40.1, Node 24.21):

text
Array by copy: high | chrome 110, firefox 115, safari 16
Array grouping: high | chrome 117, firefox 119, safari 17.4
Set methods: low | chrome 122, firefox 127, safari 17
AbortSignal.any(): high | chrome 116, firefox 124, safari 17.4
AbortSignal.timeout(): low | chrome 124, firefox 100, safari 16
BroadcastChannel: high | chrome 54, firefox 38, safari 15.4
Eng kichik talab: { chrome: '124', firefox: '127', safari: '17.4' }

Xulosa: vazifalar Chrome 124+, Firefox 127+, Safari 17.4+ da ishlaydi. Ikkita imkoniyat hali "Newly available" (low): Set metodlari va AbortSignal.timeout. Ro'yxat to'liq emas (masalan #private maydonlar, modullar ham bor), lekin ular ancha eski — talabni oshirmaydi. parseFloat bilan versiya solishtirish soddalashtirilgan: "17.10" ni "17.4" dan kichik deb hisoblaydi. Haqiqiy loyihada buni browserslist qiladi.

bash
git add 12/41-moslik/moslik.mjs 12/41-moslik/package.json
git commit -m "12/41: vazifalar brauzer mosligi o'lchovi"

package-lock.json ni ham qo'shing; node_modules — .gitignore da.

12. Real ishda

  • Har kuni: yangi metodni ishlatishdan oldin MDN sahifasining tepasidagi Baseline belgisiga qarash — 5 soniyalik odat.
  • Loyiha sozlamasi: package.json da "browserslist" va "engines" — jamoa uchun "qaysi muhitlarni qo'llaymiz" kelishuvi. Vite, Next.js kabi vositalar o'z standart nishonlariga ega va browserslist'ni o'qiydi.
  • Kutubxonalar: kutubxona mualliflari polyfill qo'shmaydi — bu ilova egasining ishi. Kutubxona README'sida "talab: Node 20+, ES2022" deb yoziladi.
  • Intervyu: "Polyfill va transpile farqi nima?", "TC39 bosqichlari qanday?", "Babel nima qiladi?" — frontend intervyularida tez-tez so'raladi.

Xulosa

  • ECMAScript — standart, JavaScript — uning amalga oshirilishi; ES2015 dan beri har yili iyunda nashr: ES2026 — 2026-yil 30-iyun.
  • Taklif 0 → 1 → 2 → 2.7 → 3 → 4 bosqichdan o'tadi; ishchi kodda — 4-bosqich (3-bosqich — polyfill bilan, ehtiyotkorlik bilan).
  • Standartda bor — brauzerda bor degani emas: Baseline (web-features), caniuse, MDN; Node uchun — uning V8 versiyasi va sinov.
  • Metod yo'q bo'lsa — feature detection va polyfill (core-js); sintaksis yo'q bo'lsa — transpile (Babel, SWC).
  • browserslist — "qaysi brauzerlar" degan bitta kelishuv, uni hamma vosita o'qiydi.
  • Polyfill — begona kod: npm'dan aniq versiya bilan, o'z saytingizdan; begona CDN'dan — faqat SRI bilan.

Keyingi dars: Nozik xatolar: race condition, xotira sizishi, flaky test va Heisenbug — faqat ba'zan chiqadigan xatolarni takrorlash va ushlash.

Manbalar

  • Ecma International: "131st General Assembly" (2026-06-30), ECMA-262 17-nashr — ecma-international.org
  • TC39: "The TC39 Process" — tc39.es/process-document; "Finished Proposals" — github.com/tc39/proposals
  • web-features va Baseline — web-platform-dx.github.io/web-features; MDN "Baseline" lug'ati — developer.mozilla.org
  • Mathias Bynens, "#SmooshGate FAQ" (2018) — developer.chrome.com/blog/smooshgate
  • Babel 8: @babel/preset-env hujjati — babeljs.io/docs/babel-preset-env; core-js — github.com/zloirock/core-js; browserslist — github.com/browserslist/browserslist
  • Sansec, "Polyfill supply chain attack hits 100K+ sites" (2024-06-25) — sansec.io; BleepingComputer (2024-06-25)
Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JS versiyalari va brauzer mosligi: ES2015 dan ES2027 gacha, Baseline va polyfill — IlmHamroh