JavaScript Evolutsiyasi Qisqa Satrlarda!
Tags: javascript, opensource, webdev, programming
Published: 2022-05-12 08:25:00

### Bismillah!
<u>_Taxminiy o'qish vaqti: ~9 daqiqa_</u>

> _**Diskleymer**: ba'zi atamalardan shundayligicha foydalanildi, tarjimasi ga'latiroq yoki notanish ko'rinmasligi uchun. Ba'zi iboralar esa ixchamroq ko'rinishga keltrildi, release -> reliz._

Assalam alaykum! Bugun siz bilan **JavaScript** (**JS**) rivojlanish tarixiga biroz nazar tashlaymiz. Hozirgi kunda eng zamonaviy va eng ko'p qo'llaniladigan tillardan hisoblangan JS oldin qanday edi va o'tgan yillar ichida qanchalik o'zgardi va kimlar o'zgartirdi. Bu maqolada JSni boshlanish tarixiga to'xtalib o'tirilmadi, agar bu haqida to'liq bilishni xohlasangiz quyidagi maqoladan o'qib olsangiz bo'ladi: [version history of javascript](https://www.educative.io/blog/javascript-versions-history)

Ko'p yillar davomida (< 2015 gacha) JS rivojlanishi (tilga yangi imkoniyatlarni qo'shib borish) juda sekin va salmoqsiz edi. Aniqroq gapiradigan bo'lsak, [ECMAScript](https://en.wikipedia.org/wiki/ECMAScript) (JS ni spesifikatsiyasiga ma'sul standard) tilni **_3.1_** versiyasida 2009 dan beri qotib qolgan edi :lock:. Solishtirish uchun ushbu [havolaga](https://www.w3schools.com/js/js_versions.asp) qaralsin. Keyinchalik bu versiya biz ko'proq tanish bo'lgan **ECMAScript 5** yoki **ES5** nomi bilan almashtirildi. Keyingi katta relizgacha JS community ancha uzoq kutib qoldi, deyarli 6 yil. Xatto ATM mashinalar ham tezroq yangilanib turiladi.

Bu vaqt mobaynida esa [TC39](https://github.com/tc39) deb nomlangan JSni stardartlashtirish guruhi bir qancha [OpenJS Foundation](https://openjsf.org/) kabi ochiq jamiyatlar yordamida ECMAScript 2015 yoki ES6 versiyasini ishlab chiqishdi va 2015 yilga kelibgina taqdim etishdi. Bu JS tarixidagi shu paytgacha kirtilgan eng katta va muhim yangilanish edi.

Bu relizda JSga kiritilgan yangi imkoniyatlarning eng asosiylari bilan quyida tanishib chiqamiz. To'liq ma'lumotni esa [ushbu](http://es6-features.org/) havoladan ko'rib olsangiz bo'ladi.

- [yangi Promise API](#yangi-promise-api) :hourglass:
- [class sintaksisi](#class-sintaksisi)
- [yagona modul tizimi] (#yagona-modul-tizimi) :full_moon:
- [arrow funksiyalar](#arrow-funksiyalar) :fire:
- [destrukturalash sintaksisi](#destrukturalash-sintaksisi)
- [meta programming](#meta-programming) :wrench:
- [block scoped ozgaruvchilar](#block-scoped-ozgaruvchilar)
- [iterator va generatorlar](#iterator-va-generatorlar) :muscle:
- [template literal](#template-literal)


### Yangi Promise API
[Promise](https://javascript.info/promise-basics) obyekti muayyan asinxron operatsiya (serverga http so'rov) bilan ancha qulay tarzda ishlash imkonini beradi. Bu mexanizmdan oldin JSda asinxron kodlar `callback` lar yordamida amalga oshirilardi lekin noqulayliklari ko'p edi. Bunga yaqqol misol qilib `callback hell` :weary: keltirish mumkin. Buni quyidagi [code-snippet](http://callbackhell.com) da ko'rishingiz mumkin: 

![Callback hell sample](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ys4llm78tc7mthzxhunp.png)

Demak `Promise`lar bizga quyidagilarni beradi:
1. Yanada ekspressiv asinxron kod yozish.
2. Yanada elegant `error handling`.

> _ekspressiv_ - qisqa satrlarda ko'p narsani namoyon eta olish.
> _elegant_ - nafis va yoqimli ko'rinish.

_Qo'shimcha: [ES7](https://javascript.info/async-await) `async/await` sintaksisi esa asinxron kodingni yanada qulaylashtirdi._

### Class sintaksisi

`Class`lar JSning `prototype` mexanizmi ustiga qurilgan abstraksiyasidir. Javadagi `class`lar bilan adashtirilmasin chunki sintaktik bir xil ko'rinishda bo'lsada, ishlash mexamizmlari fundamental darajada bir biridan farqlidir. JSda haqiqiy `Prototypal Inheritance` (aslida `Delegation`) ni to'g'ri `setup` qilish biroz murakkabroq jarayon edi, `class`lar buni elegant holatga keltirdi.
```javascript
// classlarsiz
function Person() {...}
Person.prototype.getName = function () {...}

function Student() {}
Student.prototype.getScores = function () {...}
Student.prototype = Object.create(Person.prototype);
Student.prototype.constructor = Student;

// classlar bilan
class Person {
  getName() {...}
}
class Student extends Person {
  getScores() {...}
}
```
Lekin bu degani `class`lar yaxshiroq degani emas. Uni o'ziga yarasha kamchililari bor. Bu haqida esa boshqa maqolada bafurja muhokama qilamiz. Shaxsan men uchun `class`lar JSda obyektlar bilan ishlashga turli tumanlikni olib kirdi va Javaga o'xshash kompilyatorlik tillardan kelgan dasturchilarga visual qulaylik berdi ya'ni _syntactic sugar_.

### Yagona modul tizimi

Har qanday dasturiy ta'minotda dastur kodining yaxshi strukturaviy qismlarga ajratilgani, ham mantiqiy ham jismoniy, bu eng muhim masalalardan biridir. Bunga esa modullar orqali erishiladi. Afsuski, ES6 modul tizimidan oldingi modullash tizimlarida bir qator kamchiliklar mavjud edi, misol uchun server va client uchun universal modul tizimining yo'qligi. Dastlabki modul tizimlaridan farqli o'laroq, yangi ECMAScript Modules (ESM) tizimi [statik bog'liqliklardan](https://waghetti.com/posts/2021/01/static-dependency-injection/) foydalanish uchun JS sintaksisini yaxshiladi, bu esa 4 ta muhim afzalliklarni berdi:
- Dastur kodining statik tahlili, o'lik kodni yo'q qilish (dead-code elimination) va keraksiz kodlarni topish (tree-shaking) kabi bir qancha zamonaviy dasturlash vositalarini ishini ancha samaraliroq qilishga imkon yaratdi.
- Server va client uchun modul tizimini birlashtirdi, bu esa platformaga qarab turli xil modul tizimlarini talab qilish muammosini chiroyli hal etdi. (e.g. CommonJS va AMD)
- butun dastur bo'ylab kodni qayta-qayta ishlata olishlik imkoniyatini yaxshiladi ya'ni more elegant code sharing.
- Kompilyatorlarning kodni tahlil qilish usulini optimallashtirdi. 

>Yashasin `export/import` yo'qolsin `require/define`! (bu albatta xazil edi)

### Arrow funksiyalar

Bu yangi standartdan oldin, JSda funksiyalarni yaratish uchun `function` kalitso'zi ishlatilardi, endi esa funksiyalarni ` => ` maxsus arrow sintaksisi yordamida ekspressivroq tarzda e'lon qila olamiz. Arrow funksiyalar Pythondagi lambda funksiyalar kabidir va an'anaviy funksiyalardan bir qancha [farqlari](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions) bor. Xususan, arrow funksiyalar an'anaviy funksiyalardagi `this`, `arguments` yoki `super` kabi mexanizmlarga ega emas . Bundan tashqari, `call`, `apply` va `bind` kabi scopelarni o'zgartira olishda ishlatiladigan vositalar bilan ishlatila olinmaydi.

```javascript
// ES6 dan oldin 
function add(num1, num2) {
 return num1 + num2;
}
 
// ES6 dan keyin 
const addImplicit = (num1, num2) => num1 + num2;
```
Arrow funksiyalaridan foydalanishning eng katta qulayligi sifatida `setTimeout()` va `EventTarget.addEventListener()` kabi metodlar bilan oson ishlatilishini aytish mumkin, chunki ularda odatda funksiyaning tegishli scopeda bajarilishini taʼminlash uchun [closure](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures) mexanizmini tadbiq qilinishi yoki `bind` va `apply` kabi metodlarni ishlatish talab etiladi.

### Destrukturalash sintaksisi

Obyektni destrukturalash obyektning propertiylarini qulay tarzda ajratib olishga va ularni o'zgaruvchilarga osonroq o'zlashtirishga imkon yaratadi. Bu esa dastur kodidagi tartibsizliklarni (code clutter) kamaytirishda samarali rol o'ynab kodni yanada ixcham va o'qishli ko'rinishga keltiradi.
Ko'rib o'zingiz baho bering:

```javascript
const state = {
 name: "Ahmad",
 age: 25,
 address: {
   zipCode: 7711,
   city: "Tashkent"
 }
}

const { name, address: { zipCode } } = state; // cool!
// solishtirish uchun
const zipCode = state.address.zipCode;
const name = state.address.zipCode;
```

### Meta programming 

**[Proxy](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy)** obyekti sizga dasturni ishlash jarayonida (runtime) meta levelda muayyan operatsiyalarni intersept qila olish va o'ziga qulay shaklga keltira olish imkoniyatlarini taqdim etadi.

> **_intersept qilish_** - dasturning biron operatsiyasini bajarilish jarayoni orasiga suqulib kirib unga ta'sir o'tkazish, zimdan kuzatish yoki o'zgartira olishlik. (dasturni ishlash jarayoni bu RAMda aktiv ishchi holatda bo'lishlik degani)
**_meta level_** - ya'ni runtime vaqtida dasturlash tilining fundamental mexamizmlari ishlashiga aralasha olish yoki o'zgartira olish 

`Proxy`lar muayyan turdagi muammolarni hal qilishda juda foydali mexanizm hisoblanadi. _**[Cross cutting aspects](https://en.wikipedia.org/wiki/Cross-cutting_concern)**_ bunga yaqqol misol bo'la oladi. Real misol sifatida esa Vue3 ning [reaktiv](https://vuejs.org/guide/extras/reactivity-in-depth.html#how-reactivity-works-in-vue) tizimini keltirish mumkin, ular `Proxy`lardan juda samarali foydalanishgan va oldingi versiyadagi hacky yechimni (`Object.defineProperties()`) `Proxy`lar bilan almashtirishgan. Bu haqida boshqa maqolalarimizda batafsil to'xtalib o'tamiz.

### Iterator va generatorlar

> ES6 dagi menga eng yoqqan imkoniyatlardan biri

Bular tilning eng kam tilga olinadigan biroq eng ko'p ishlatiladigan imkoniyatlarini asosida yotuvchi mexanizmlardir (`Promise`, `async/await`, etc). JSchilar uchun katta imkoniyatlarni ochib beradi. Bular alohida e'tiborga loyiq mazvular bo'lgani uchun ular haqida ham alohida post yozish istagi bor. Hozircha esa quyidagi [code-snippet](https://gist.github.com/humoyun/1bbdb4b36300c350e0c63db73b82fbcb) lar bilan cheklanamiz:

```javascript
// DOM traversal 
const parent = document.createElement("div");
parent.innerHTML = `
  <div id="subTree">  
    <form>    
      <input type="text"/>  
    </form>  
    <p>Paragraph</p>
    <span>Span</span>
  </div>
`;
const subTree = parent;

// recursive yechim
const traverseDOMRecursive = function (elem, cb) {
  cb(elem);
  elem = elem.firstElementChild;
  while (elem) {
    traverseDOMRecursive(elem, cb);
    elem = elem.nextElementSibling;
  }
};
function callback(element) {
  console.assert(element !== null, element.nodeName);
}
traverseDOMRecursive(subTree, callback);

// generatorlar bilan
const traverseDOMGenerator = function* (elem) {
  yield elem;
  elem = elem.firstElementChild;
  while (elem) {
    yield* traverseDOMGenerator(elem);
    elem = elem.nextElementSibling;
  }
};
// for loop ni ichida ishlatilishiga e'tibor bering
for (let element of traverseDOMGenerator(subTree)) {
  console.log("element", element.nodeName);
}
```
Endi esa iteratorlarga misol:

```javascript
class Range {
  constructor(...args) {
    this.start = args.length <= 1 ? 0 : args[0];
    this.end = args.length <= 1 ? args[0] || 0 : args[1];
    this.step = args.length <= 2 ? 1 : args[2];
  }
  [Symbol.iterator]() {
    return this;
  }
  next() {
    if (this.end > this.start) {
      const result = { done: false, value: this.start };
      this.start = this.start + this.step;
      return result;
    } else return { done: true, value: undefined };
  }
}

function range(...args) {
  return new Range(...args);
}

// ajoyib emasmi!
console.log([...range(4)]);
console.log([...range(2, 5)]);
console.log([...range(1, 10, 3)]);
```

### Block scoped o'zgaruvchilar

ES6 tilga yangi o'zgaruvchilarni olib kirdi va ular `var` ni o'rnini deyarli to'liq egalladi. ES6 gacha, JSda faqatgina funksional va global scopelar bor edi, `let` va `const` qo'shilishi tufayli JSda endi [block scope](https://dev.to/sandy8111112004/javascript-introduction-to-scope-function-scope-block-scope-d11#:~:text=A%20block%20scope%20is%20the,only%20within%20the%20corresponding%20block.) ham mavjud. `var` bilan e'lon qilingan o'zgaruvchilarda `locality` mexanizmi yo'q edi shuning uchun odatda global scope da e'lon qilingan boshqa o'zgaruvchilar bilan to'qnashuv bo'lishini oldini olish qiyin edi. Block scope esa bu muammoni hal qildi.

> _**locality**_ - biron o'zgaruvchining dastur kodining faqat o'ziga tegishli qismidagina `{}` mavjud bo'la olishi. 
```javascript
let x = 5;
 
function blockExample() {
 let x = 2 // bu funksional scope
 if(x >= 3) {
   let x = 10; // bu block scope
   console.log(x, "if blokining ichida");
 } else {
   let x = 1;
   console.log(x, "else blokining ichida");
 }
 console.log(x, "funksiyani ichidagi");
}
 
blockExample();
console.log(x, "global x");
```
`const` o'z nomi bilan constanta ya'ni o'zgarmas qiymatni bildiradi va u bilan e'lon qilingan o'zgaruvchilarga yangi qiymat berishga urinilsa dastur xatolik qaytaradi.

### Template literal

Stringlar bilan ishlash imkoniyatlarini yanada kengaytirdi. Qulay interpolyatsiya `${}` sintaksini olib kirdi.

```javascript
let name = "Ahmad";
const HOLIDAY = "Iyd al-Fitr"; 
// ES6 dan oldin: 
console.log(name + "ning sevimli bayrami bu " + HOLIDAY);
// ES6 dan keyin:
console.log(`${name}ning sevimli bayrami bu ${HOLIDAY}`);
// yoki
const multiLineString = `Cross-cutting concerns are parts 
of a program that rely on or must affect many other 
parts of the system`
```

Va hokazo!

> Yana bir eng muhim yangilik bu: JS ni reliz sikli (tilga yangi imkoniyatlarni davomiy tarzda qo'shib borish davri) yillik ko'rinishga o'tkazildi.


## Biroz TC39 haqida

Endi TC39 haqida bir-ikki luqma gap aytamiz. Bu ishchi guruh  yetakchi web kompaniyalar a'zolaridan tashkil topgan bo'lib asosiy maqsadi ECMAScriptni rivojlantirib borishdan iborat, bu esa o'z navbatida JSni standartlashtirib borish degani. Bundan tashqari TC39 JSchilar keng ommasiga tilga o'zlarining takliflarini ([proposal](https://github.com/tc39/proposals)) berish imkoniyatini bajaruvchi platforma sifatida ham faoliyat yuritadi. Bu takliflar ochiq shaklda butun dunyodagi webchilar ommasiga qo'yiladi va muayyan vaqt davomida belgilangan [struktura](https://tc39.es/process-document/) bo'yicha bir nechta bosqichlarda muhokama qilinadi. Quyida bu haqida biroz to'xtalamiz. 

### TC39 bosqichlari

- **_Stage 0 (strawman)_**: Bu norasmiy bosqich bo'lib, taklif har qanday erkin shaklda bo'lishi mumkin, demak hamma ishtirok eta oladi. Taklifingizni kirgazish uchun esa TC39ning a'zosi bo'lishingiz yoki ECMA Internationalga [registratsiya](https://tc39.github.io/agreements/contributor.) qilishingiz talab etiladi. Registratsiyadan so'ng taklifingizni [esdiscuss](https://esdiscuss.org) mailing listi orqali bildirishingiz yoki boshqa takliflarni kuzatib borishingiz mumkin.

- _**Stage 1 (proposal)**_:  **_Strawman_** dan so'ng, biron **TC39** a'zosi sizning taklifingiz keyingi bosqichga o'tish uchun qo'llab-quvvatlashi kerak. Bu a'zo berilgan taklif nima uchun foydali ekanligini tushuntirishi va u amalga oshirilganda qanday ishlashi va ko'rinishini tasvirlashi kerak :hatched_chick:.

- _**Stage 2 (draft)**_:  Bu bosqichda taklifning to'liq spesifikatsiyasi ishlab chiqiladi va eksperimental hisoblanadi (do it at your own risk ☢️ ). Agar taklif bu bosqichga yetib kela olsa, odatda **TC39** bu taklifni qachondir JSni spesifikatsiyasiga kiritilishini kutadi.

- **_Stage 3 (candidate)_**: Bu bosqichda berilgan taklif to'liq deb hisoblanadi va imzolanadi. Bu bosqichdan keyin taklifga o'zgartirishlar kiritish juda ham kam bo'lib, faqatgina juda kiritik muammolari topilsagina va ko'p muddatli foydalanishdan so'ngina amalga oshiriladi. Ushbu bosqichda taklifni qo'rqmasdan ishlatsangiz bo'ladi chunki ma'lum muddatdan so'ng, taklif xavfsiz tarzda so'nggi bosqichga o'tkaziladi.

- **_Stage 4 (finished)_**: Bu yakuniy bosqich hisoblanadi. Agar taklif bu bosqichgacha yetib kelsa uni endi bemalol formal tarzda ECMAScript standartining spesifikatsiyasiga qo'shildi desa bo'ladi :checkered_flag:. 

Bunday sog'lom va dinamik usulda tilga yangi imkoniyatlarni kiritib borish juda ham muhim jarayon hisoblanadi. Buning natijasida JS bugungi dunyoning tez o'zgarib boruvchi va murakkab talablariga labbay deb javob bera oladi.
Quyida ushbu taklif (proposal) lardan ba'zilarini keltirib o'tamiz.

- [Private class `field`lari](https://github.com/tc39/proposal-class-fields) va nihoyat `class`larda `access modifier`larni (`private`,`static`) qo'llash imkonini beruvchi sintaksis.
- [`Observable`lar](https://github.com/tc39/proposal-observable) `stream`larga asoslangan reaktiv dasturlash paradigmasini olib kiradi JSga. Shaxsan menga eng yoqqan takliflardan biri. Bu haqida ham alohida maqola yozish niyat bor. RxJS (Angular) bilan ishlab ko'rganlar bo'lsa buni nimaligini juda yaxshi tushunishadi, endi bu library emas balki native :rocket: !!! 
- [Pipeline operatori](https://github.com/tc39/proposal-pipeline-operator) UNIXdagi `pipe` utilitasiga o'xshash asosan funksional tillarga tegishli bo'lgan mexanizmni JS fuksiyalarida ishlatish imkonini beradi.
- [Yangi `bind` operatori](https://github.com/tc39/proposal-bind-operator) `Function.prototype.bind` ni yanada elegant tarzda ishlatish imkonini beruvchi yangi sintaksis


>_Ushbu maqola Internetdan olingan ma'lumotlar yordamida tayyorlandi. Har qanday taklif va mulozalar bosh ustiga, ularni pastdagi sharhlar bo'limida qoldirishingiz mumkin. Maqsadimiz o'zbek tilida IT bilan bo'gliq sifatli contentni ko'paytirish va ularni hammaga qulay uslubda tarqatishdir. Bunda eng katta muammolarimizdan biri bu sohaga oid inglizcha atamalarni qanday qilib tushinarli tarzda, o'z ma'nosidan chiqib ketmagan holda qisqa va lo'nda shaklda yetkazishdir. Chunki to'g'ridan to'g'ri (direct) tarjima ko'p hollarda haddan tashqari uzun, tushunarsiz va o'zining dastlabki ma'nosidan chiqib ketgan shaklga kelib qolishidir. Shuning uchun **sarbast** (erkin) uslubni (postimizda boshida ham bu haqida biroz to'xtalgandik) sinab ko'rishga qaror qildik. Haligi aytishgandek: Best of both worlds :) !_