JavaScript Evolutsiyasi Qisqa Satrlarda!
Humoyun Ahmad
Posted on May 12, 2022
Bismillah!
Taxminiy o'qish vaqti: ~9 daqiqa
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
Ko'p yillar davomida (< 2015 gacha) JS rivojlanishi (tilga yangi imkoniyatlarni qo'shib borish) juda sekin va salmoqsiz edi. Aniqroq gapiradigan bo'lsak, ECMAScript (JS ni spesifikatsiyasiga ma'sul standard) tilni 3.1 versiyasida 2009 dan beri qotib qolgan edi π. Solishtirish uchun ushbu havolaga 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 deb nomlangan JSni stardartlashtirish guruhi bir qancha OpenJS Foundation 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 havoladan ko'rib olsangiz bo'ladi.
- yangi Promise API β
- class sintaksisi
- yagona modul tizimi π
- arrow funksiyalar π₯
- destrukturalash sintaksisi
- meta programming π§
- block scoped ozgaruvchilar
- iterator va generatorlar πͺ
- template literal
Yangi Promise API
Promise 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
π© keltirish mumkin. Buni quyidagi code-snippet da ko'rishingiz mumkin:
Demak Promise
lar bizga quyidagilarni beradi:
- Yanada ekspressiv asinxron kod yozish.
- Yanada elegant
error handling
.
ekspressiv - qisqa satrlarda ko'p narsani namoyon eta olish.
elegant - nafis va yoqimli ko'rinish.
Qo'shimcha: ES7 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.
// 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 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'qolsinrequire/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 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.
// 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 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:
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 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 bunga yaqqol misol bo'la oladi. Real misol sifatida esa Vue3 ning reaktiv 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 lar bilan cheklanamiz:
// 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:
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 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.
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.
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) berish imkoniyatini bajaruvchi platforma sifatida ham faoliyat yuritadi. Bu takliflar ochiq shaklda butun dunyodagi webchilar ommasiga qo'yiladi va muayyan vaqt davomida belgilangan struktura 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 qilishingiz talab etiladi. Registratsiyadan so'ng taklifingizni esdiscuss 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 π₯.
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 π.
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 va nihoyatclass
lardaaccess modifier
larni (private
,static
) qo'llash imkonini beruvchi sintaksis. -
Observable
larstream
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 π !!! -
Pipeline operatori UNIXdagi
pipe
utilitasiga o'xshash asosan funksional tillarga tegishli bo'lgan mexanizmni JS fuksiyalarida ishlatish imkonini beradi. -
Yangi
bind
operatoriFunction.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 :) !
Posted on May 12, 2022
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.