Nega
Bilamiz
Xo'sh, nega metodni
Qizig'i shundaki, biz bu yerda
JavaScript'da tiplar dinamik bo'lgani uchun ko'pincha shunga o'shash surprizlarni uchratish mumkin. Maslahatim esa, har doim dokumentatsiyalarni ochib o'qing!
#js #jsdaily #regexp
/[A-Za-z]/.test()
natijasi βtrueβ?Bilamiz
.test()
metodi string qabul qiladi va uni RegExp
'ga ko'ra tekshiradi. Agar string mos kelsa true
, aks holda false qaytaradi./[A-Za-z]/
esa ingliz alifbosidagi harflarni aniqlovchi RegExp
.Xo'sh, nega metodni
/[A-Za-z]/
bilan argumentsiz chaqirsak true qaytaradi? RegExp'ni bo'sh qiymatga nisbatan tekshirsak false chiqishi kerakmasmidi?Qizig'i shundaki, biz bu yerda
.test()
ni aslida .test(undefined)
holatida chaqiryapmiz. Metod argument sifatida string olishini aytdik. Shuning uchun undefined
string'ga konversiya bo'ladi va 'undefined'
ga aylanadi. 'undefined'
esa ingliz alifbosidagi harflardan iborat so'z! Demak natija true
bo'lishi to'g'ri!JavaScript'da tiplar dinamik bo'lgani uchun ko'pincha shunga o'shash surprizlarni uchratish mumkin. Maslahatim esa, har doim dokumentatsiyalarni ochib o'qing!
#js #jsdaily #regexp
π3
This media is not supported in your browser
VIEW IN TELEGRAM
Bugun yilning 256-kuni. Barcha hamkasblarimni Dasturchilar kuni bilan tabriklayman!
πππ
πππ
This media is not supported in your browser
VIEW IN TELEGRAM
input.valueAsNumber
"Numeric" input elementlarning qiymatini JS orqali o'qiganimizda ularni har doim
Agar input elementlarning
Tepadagi qisqa demonstratsiya StackBlitz'ning Twitter sahifasidan uxlatildi.
#js #jsdaily #tips
"Numeric" input elementlarning qiymatini JS orqali o'qiganimizda ularni har doim
Number
tipiga konversiya qilamiz. Chunki elementning .value
field'i bizga har doim String
qaytaradi.Agar input elementlarning
.valueAsNumber
field'ini ishlatsak bu bosh og'riqdan qutilamiz. Bu field faqat "numeric" inputlar bilan ishlaydi. Ya'ni input type'imiz "number"
, "date"
, "datetime",
yoki "range"
bo'lishi kerak. Aks holda bu field qiymati NaN
ga teng bo'ladi. Hattoki kirilgan qiymat son bo'lsa ham, lekin input type "text"
bo'lsa, .valueAsNumber
bizga NaN
qaytaradi.Tepadagi qisqa demonstratsiya StackBlitz'ning Twitter sahifasidan uxlatildi.
#js #jsdaily #tips
π6
Object.is() vs ===
Ularning asosiy farqi
Demak,
Quyidagi misollarni ko'rib, o'zingiz ham tekshirib ko'ring.
Object.is()
metodini ===
operatori bilan ko'p holatlarda bemalol almashtirib ishlatsak bo'ladi. Lekin ular bir-biriga to'liq ekvivalent emas.Ularning asosiy farqi
Object.is()`ning `NaN
va ishorali nollardagi holatdir. Ishorali nollar bu: -0
va +0
.Demak,
===
operatori 2 ta NaN
qiymatni tekshirarkan false
qaytaradi. Lekin Object.is(NaN, NaN)
esa true
natijasini beradi.Quyidagi misollarni ko'rib, o'zingiz ham tekshirib ko'ring.
`string.charAt(i)` vs `string[i]`
String'dagi bitta simvolni
Lekin, index'imiz "boshqachaoq" qiymat bo'lsachi? π€
Tekshiramiz:
Demak,
Lekin
Albatta "type coercion"! Ya'ni biz bergan qiymat bilvosita songa, Number'ga aylanib ketyapti:
Shunday ekan, agar mana bunday qilsak kodimiz kutilgan natijani beradi:
String'dagi bitta simvolni
string[index
] yoki string.charAt(index
) usulida olish mumkin. Agar index'imiz [0, `string.length - 1`] oralig'ida bo'lsa, bu 2 usulning bir biridan farqi yo'q.Lekin, index'imiz "boshqachaoq" qiymat bo'lsachi? π€
Tekshiramiz:
'hello'[NaN]; // undefined
'hello'.charAt(NaN); // 'h'
'hello'[undefined]; // undefined
'hello'.charAt(undefined); // 'h'
Demak,
[NaN
] bilan holat mantiqan olinsa to'g'ri. Lekin
.charAt(NaN)
'chi? Bu yerda nima bo'lyapti? Albatta "type coercion"! Ya'ni biz bergan qiymat bilvosita songa, Number'ga aylanib ketyapti:
undefined -> 0
charAt(undefined) -> charAt(0)
Shunday ekan, agar mana bunday qilsak kodimiz kutilgan natijani beradi:
'hello'.charAt('00') // 'h'
π3
Brogrammist
`string.charAt(i)` vs `string[i]` String'dagi bitta simvolni string[index] yoki string.charAt(index) usulida olish mumkin. Agar index'imiz [0, `string.length - 1`] oralig'ida bo'lsa, bu 2 usulning bir biridan farqi yo'q. Lekin, index'imiz "boshqachaoq" qiymatβ¦
string.charAt(index)
'ning yana bir xislati, agar index butun son bo'lmasa, uni o'zidan kichik eng katta butun songa yaxlitlaydi:
'hello'.charAt(1.23) // 'e'
// 1.23 -> 1
Unda index manfiy bo'lsachi? Yoki string'ning uzunligidan katta bo'lsachi?
Bu holatda
.charAt
bo'sh string qaytaradi:
'hello'.charAt(100); // ''
'hello'.charAt(-34); // ''
Tabiiyki, yuqoridagi holatlarda
string[index]
usuli shunchaki undefined
natijasini beradi.#js #jsdaily #tips
π3
Unicode string ustida iteratsiya
Quiydagi misolga e'tibor bering:
Agar bilmagan bo'lsangiz, qanday qilib unicode string'lar ustida to'g'ri iteratsiya qilishni ham bilib oling:
Quiydagi misolga e'tibor bering:
const msg = 'Hellπ¬';
// for ... in
for (let i in msg) {
console.log(msg[i]);
}
// Output:
// 'H', 'e', 'l', 'l', '
??'
Bilarmidingiz, "for...in" unicode string'lar bilan ishlamasligini?Agar bilmagan bo'lsangiz, qanday qilib unicode string'lar ustida to'g'ri iteratsiya qilishni ham bilib oling:
// for ... of
for (let c of msg) {
console.log(c);
}
// Output:
// 'H', 'e', 'l', 'l', 'π¬'
#js #jsdaily #tipsπ20
JavaScript'da `void` operatori
Yuqoridagi misollardan ko'rinib turibdiki "void" qilingan ifoda qiymati undefined'ga teng.
Agar biror funksiya "return" qiladigan qiymat kerak bo'lmasa, uning oldiga
Qiziq fakt: Ba'zi minifikatorlar
#js #jsdaily #tips
void
o'zidan keyin keladigan ifoda qiymatini `undefined`ga aylantirib yuboradi:
void 0 === undefined; // true
void 1 === undefined; // true
void 'Hello' === undefined; // true
Yuqoridagi misollardan ko'rinib turibdiki "void" qilingan ifoda qiymati undefined'ga teng.
Agar biror funksiya "return" qiladigan qiymat kerak bo'lmasa, uning oldiga
void
qo'yish yaxshi amaliyot (ya'ni best practice) hisoblanadi:
button.onclick = () => void doSomething();
Qiziq fakt: Ba'zi minifikatorlar
undefined
uzun so'z bo'lgani uchun uni void 0
bilan almashtirib ketadi.#js #jsdaily #tips
π23
JavaScript'da link yaroqliligini tekshirish
Linklar o'ziga yarasha sintaksis/standartga ega. Masalan:
"https://google.com?q=cat&cr=UZ"
Bu link yaroqli (valid), chunki unda standart bo'yicha protokol, unda keyin "://" qo'yilib, keyin domain, keyin esa "path" va "query" parametrlar to'g'ri qo'yilgan.
Buni biz "regular expression" orqali tekshirishimiz mumkin. Lekin ishoning bunaqa RegExp'ni yozishni xohlamagan bo'lardingiz.
Kutubxona (library) ishlatsakchi? To'g'risi, proyektingiz kattalashgani sari har bir bayt siz uchun qimmatli. Ularni keraksiz joylari ko'p qandaydir kutubxonaga sarflashga arzimaydi.
Gapning qisqasi JavaScriptning o'zida linklar bilan ishlovchi "built-in" interfeys bor. Bu
Quyidagi funksiyani bemalol Copy&Paste qilishingiz mumkin:
#js #jsdaily #tips
Linklar o'ziga yarasha sintaksis/standartga ega. Masalan:
"https://google.com?q=cat&cr=UZ"
Bu link yaroqli (valid), chunki unda standart bo'yicha protokol, unda keyin "://" qo'yilib, keyin domain, keyin esa "path" va "query" parametrlar to'g'ri qo'yilgan.
Buni biz "regular expression" orqali tekshirishimiz mumkin. Lekin ishoning bunaqa RegExp'ni yozishni xohlamagan bo'lardingiz.
Kutubxona (library) ishlatsakchi? To'g'risi, proyektingiz kattalashgani sari har bir bayt siz uchun qimmatli. Ularni keraksiz joylari ko'p qandaydir kutubxonaga sarflashga arzimaydi.
Gapning qisqasi JavaScriptning o'zida linklar bilan ishlovchi "built-in" interfeys bor. Bu
UR
L obyekti. URL
obyekti konstruktori argument sifatida string oladi. Agar string yaroqsiz link bo'lsa "exception" otiladi. Shuning uchun uni "try-catch" bilan o'rash kerak.Quyidagi funksiyani bemalol Copy&Paste qilishingiz mumkin:
function isValidURL(url) {
try {
new URL(url);
return true;
} catch (error) {
return false;
}
};
isValidURL("https://google.uz");
// true
isValidURL("https//invalidcom");
// false
#js #jsdaily #tips
π25
Brogrammist
JavaScript'da link yaroqliligini tekshirish Linklar o'ziga yarasha sintaksis/standartga ega. Masalan: "https://google.com?q=cat&cr=UZ" Bu link yaroqli (valid), chunki unda standart bo'yicha protokol, unda keyin "://" qo'yilib, keyin domain, keyin esa "path"β¦
Regular expression bilan linklarni tekshirishga qiziqqanlar uchun "anchorme" kutubxonasidan havola.
Yana qaytaraman, bunaqa RegExp yozgingiz kelmagan bo'lardi.
Yana qaytaraman, bunaqa RegExp yozgingiz kelmagan bo'lardi.
π8π2
Number'larning ham metodlari bor
JavaScript'da primitiv tiplar obyekt kabi ishlatilishi mumkin. Chunki primitivlarning metodlari yoki property'larini ishlatarkanmiz JS bizga o'sha primitivni mos obyekt bilan o'rab beradi (manbaa). Quyida aynan Number'larning "metod"larini ko'rib chiqamiz:
1.
"Exponential notation" atamasining o'zbekchasi bilsangiz, iltimos, kommentlarda qoldiring.
2.
3.
JavaScript'da primitiv tiplar obyekt kabi ishlatilishi mumkin. Chunki primitivlarning metodlari yoki property'larini ishlatarkanmiz JS bizga o'sha primitivni mos obyekt bilan o'rab beradi (manbaa). Quyida aynan Number'larning "metod"larini ko'rib chiqamiz:
1.
toExponenti
al() - sonni eksponensial (mantissa va o'nning darajasi) ifodaga o'giradi.
const num = 12000;
num.toExponential(); // '1.2e+4'
"Exponential notation" atamasining o'zbekchasi bilsangiz, iltimos, kommentlarda qoldiring.
2.
toFixe
d(n) - sonni o'nli kasrda ko'rinishida nuqtadan keyin n ta son qoldirgan holda ifodalaydi. n soni [0, 100] oralig'ida bo'lishi shart:
const num = 12000;
num.toFixed(2); // '12000.00'
const num1 = 3.141592;
num1.toFixed(1); // '3.1'
num1.toFixed(0); // '3'
3.
toPrecisio
n(n) - sonning n ta muhim raqamini saqlab qolgan holda eksponensial ko'rinishda ifodalaydi. n soni [1, 100] oralig'ida bo'lishi shart.toFix
ed() dan farqi shuki, bu metod nuqtadan keyin emas, balki sonning boshidan boshlab muhim raqamlani hisobga oladi:
(12).toPrecision(4); // '12.00'
(1234).toPrecision(2); // '1.2e+4'
(1234).toPrecision(3); // '1.23e+4'
π5π€1
4.
Xullas, istagancha konvertatsiya qilavaramiz.
Shuni sezib qoldimki
Zo'r-a?
#js #jsdaily #tips
toString(radix
) - sonnni boshqa sanoq sistemasiga o'girib beradi:
// 10 likdan 16 likka
(1234).toString(16); // '4d2'
// 10 likdan 8 likka
(789).toString(8); // '1425'
// 10 likdan 2 likka
(123).toString(2); // '1111011'
// 16 likdan 10 likka
(0x5ac).toString(10); // '1452'
// 8 likdan 10 likka
(0123).toString(10); // '83'
Xullas, istagancha konvertatsiya qilavaramiz.
Shuni sezib qoldimki
radix
parametri istalgan son bo'lishi mumkin ekan, faqat 2-lik, 8-lik kabilar emas:
// 8 likdan 5 likka
(065).toString(5); // '203'
// 16 likdan 27 likka
(0xdac).toString(27); // '4lh'
Zo'r-a?
#js #jsdaily #tips
π28π1
Number'larni
toString(?radix)
orqali istalgan sanoq sistemasiga o'tkazish mukinligini ko'rdik. Aytib o'tish kerak, bu yerda radix
parametri [2, 36] intervalida bo'lishi kerak. Aks holda metod xatolik otadi. `radix`ning o'zi ixtiyoriy parametr va "default" qiymati 10 ga teng.π6
Aytgancha, sonlarni boshqa sanoq sistemalardan 10 likka o'tkazish uchun
String'ni number'ga o'girishning boshqa usullari ham bor. Ularning farqlari haqida keyingi postlarda yozishga harakat qilaman.
Number.parseInt(string, ?radi
x) metodidan foydalanamiz. parseI
nt ham global funksiya bo'lgani uchun, shunchaki o'zini ishlatsa ham bo'ladi, ya'ni Number.parseI
nt qilib o'tirmasdan:
// 16 likdan 10 likka
parseInt('ff', 16); // 255
// 13 likdan 10 likka
parseInt('c', 13); // 12
parseIn
t asosan, o'z nomi bilan, "integer" (butun son) qiymatni berilgan string'dan o'qish uchun ishlatiladi. Masalan o'nli kasrning butun qismini olish yoki string'ni number'ga aylantirish uchun:
parseInt('12.34'); // 12
parseInt('-45'); // -45
String'ni number'ga o'girishning boshqa usullari ham bor. Ularning farqlari haqida keyingi postlarda yozishga harakat qilaman.
π21
Copy&Paste'ni bloklash
Web-dasturingiz foydalanuvchilaridan qarg'ish olishni xohlaysizmi? Samarali usullaridan biri "copy&paste" imkoniyatini taqiqlash bo'lsa kerak:
Web-dasturingiz foydalanuvchilaridan qarg'ish olishni xohlaysizmi? Samarali usullaridan biri "copy&paste" imkoniyatini taqiqlash bo'lsa kerak:
const input = document.querySelector('input');
input.addEventListener(
'copy',
event =>
event.preventDefault()
);
input.addEventListener(
'paste',
event =>
event.preventDefault()
);
π30π2π±1
Brogrammist
Copy&Paste'ni bloklash Web-dasturingiz foydalanuvchilaridan qarg'ish olishni xohlaysizmi? Samarali usullaridan biri "copy&paste" imkoniyatini taqiqlash bo'lsa kerak: const input = document.querySelector('input'); input.addEventListener( 'copy', eventβ¦
Albatta "copy&paste" imkoniyatini bloklash ba'zida o'rinli. Masalan, foydalanuvchi email yoki parolini tasdiqlash uchun yana kiritishi kerak bo'lsa, "paste"ni o'chirib qo'yish mumkin. Yoki, shunga o'xshash "himoyalanishi" kerak bo'lgan ma'lumotlarni "himoyalash" uchun.
Siz o'zingiz bu imkoniyatni qanday holatlarda bloklash o'rinli deb o'ylaysiz?
Nega "himoya"ni qo'shtirnoq ichida yozganimni hamma tushundi degan umiddaman.
Siz o'zingiz bu imkoniyatni qanday holatlarda bloklash o'rinli deb o'ylaysiz?
Nega "himoya"ni qo'shtirnoq ichida yozganimni hamma tushundi degan umiddaman.
π15π3
Proxy obyektini bilarmidingiz?
Masalan, eng sodda misol, obyektda biz bergan maydon bo'lmasa "undefined" o'rniga defolt qiymat qaytarish:
Yoki setterga validatsiya qo'shishimiz mumkin:
Aytgancha, proksi obyekt birinchi obyektimizni to'liq "overwrite" qilishi kerak. Chunki ularning ikkovi ham kodimizda bo'lishi chalkash holatlarni yuzaga keltiradi. Shuning uchun har doim bunday qiling:
Proxy(object, handl
er) bizga obyektlar uchun proksi obyekt yaratish imkonini beradi. Bu bilan biz obyetklardagi fundamental operatsiyalarni "intercept/override" qilishimiz mumkin. Ya'ni ularni o'zimizga kerakli ravishda ishlaydigan qila olamiz.Masalan, eng sodda misol, obyektda biz bergan maydon bo'lmasa "undefined" o'rniga defolt qiymat qaytarish:
"
const dict = {
defolt: "default",
maydon: "field",
};
const proxy = new Proxy(dict, {
get(target, key, receiver) {
// agar `key` mavjud bo'lsa,
// mos qiymat qaytaramiz
if (target[key])
return target[key];
// agar `key` yo'q bo'sa,
// `key`ning o'zini
return key;
},
});
console.log(proxy.maydon);
// "field"
console.log(proxy.nimadir);
// "nimadir
Yoki setterga validatsiya qo'shishimiz mumkin:
const proxy = new Proxy(dict, {
set(target, key, val) {
if (typeof val !== "string")
throw new TypeError("Faqat string qiymatlar olinadi!");
target[key] = val;
return true;
},
});
Aytgancha, proksi obyekt birinchi obyektimizni to'liq "overwrite" qilishi kerak. Chunki ularning ikkovi ham kodimizda bo'lishi chalkash holatlarni yuzaga keltiradi. Shuning uchun har doim bunday qiling:
let obj = {...};
obj = new Proxy(obj, handler);
π13
"Eee akaa, bu bo'ganku! Obyektlarda getter/setter'lar bor-ku o'zi!"
deyotgan bo'lsangiz, haqsiz. Lekin Array'da getter/setter yo'q-ku!
deyotgan bo'lsangiz, haqsiz. Lekin Array'da getter/setter yo'q-ku!
let ages = [12, 6, 75];
ages = new Proxy(ages, {
set(target, key, val) {
if (typeof val !== "number")
throw new TypeError("Faqat son qiymatlar olinadi!");
if (val < 0 || val > 120)
throw new TypeError("Odamlar buncha yashamaydi!");
target[key] = val;
return true;
},
});
π15
Yana bir zo'r use-case bu funksiyalarni proksilash. Aytaylik qandaydir kutubxonadan foydalanyapmiz va uning o'znini o'zgartirolmasak, uni proksilashimiz mumkin:
Albatta buni soddaroq qilib, funksiyani yangi funksiya bilan o'rab ishlatsak ham bo'ladi. Asosiysi holatga qarab, vaziyatga eng mos tushadigan usuldan foydalanish.
import fancy from "fancy";
fancy = new Proxy(fancy, {
apply(target, thisArg, argumentList) {
return Reflect.apply(
target,
thisArg,
argumentList
);
},
});
Albatta buni soddaroq qilib, funksiyani yangi funksiya bilan o'rab ishlatsak ham bo'ladi. Asosiysi holatga qarab, vaziyatga eng mos tushadigan usuldan foydalanish.
π16
JavaScript'ning sinxronligi
Oldin JavaScript nimaligiga javob beraylik. JavaScript bu - ECMAScript spetsifikatsiyasi bo'yicha ishlab chiqilgan til. Ya'ni ECMAScript bu - standart, JavaScript esa o'sha standartning implementatsiyasi. (Yuzaki tushuntirish bo'ldi,chunki bu mavzu uchun alohida post yozsa arziydi.)
JS kodimiz ishga tusharkan, interpretator kodimizni o'ngdan chapga, tepadan pastga qatorma-qator o'qishini bilamiz. Bizning yozgan har bitta amal ketma-ket, sinxron ravishda bajariladi. Masalan:
Natija:
Ko'rinib turibdiki, "bigProcess()" tugamas ekan, undan keyingi kodimiz ishga tushmaydi. Ya'ni kodimiz bajarilishi shu joyda bloklanib qoladi. Eng yomon tarafi, bu kodni brauzerda ishlatarkanmiz, bu og'ir operatsiya oxiriga yetmaguncha butun sahifa qotib qoladi. Hatto CSS bilan yozilgan animatsiyalargacha muzlaydi.
Buning sababi, JS "single-threaded"(shunga o'zbekcha nom topish kerak) va veb-sahifadagi barcha operatsiyalar o'sha thread'da bajariladi. Bunga HTML'ni taxlil qilinishi ham, CSS stillarni biriktirilish ham kiradi. Bularning barchasini esa hosdisalar sikli ("event loop") ma'lum ketma-ketlikda bajarilishini taminlaydi. Hodisalar sikli "call stack"ni, "callback queue"ni, DOMdagi o'rgarishlarni va boshqalarni kuzatib turadi. Ularning birortasida qilinadigan ish paydo bo'lsa, o'sha ishlar asosiy "thread"da bajariladi.
"Event loop" mavzusining o'zi ham juda katta va qiziq mavzu. Bu haqida ham keyinroq post yozaman.
Oldin JavaScript nimaligiga javob beraylik. JavaScript bu - ECMAScript spetsifikatsiyasi bo'yicha ishlab chiqilgan til. Ya'ni ECMAScript bu - standart, JavaScript esa o'sha standartning implementatsiyasi. (Yuzaki tushuntirish bo'ldi,chunki bu mavzu uchun alohida post yozsa arziydi.)
JS kodimiz ishga tusharkan, interpretator kodimizni o'ngdan chapga, tepadan pastga qatorma-qator o'qishini bilamiz. Bizning yozgan har bitta amal ketma-ket, sinxron ravishda bajariladi. Masalan:
function bigProcess() {
let sum = 0;
let i = 100000000;
while (i--) sum += i;
return sum;
}
console.log("start");
console.log(bigProcess());
console.log("end");
Natija:
> start
> 4999999950000000
> end
Ko'rinib turibdiki, "bigProcess()" tugamas ekan, undan keyingi kodimiz ishga tushmaydi. Ya'ni kodimiz bajarilishi shu joyda bloklanib qoladi. Eng yomon tarafi, bu kodni brauzerda ishlatarkanmiz, bu og'ir operatsiya oxiriga yetmaguncha butun sahifa qotib qoladi. Hatto CSS bilan yozilgan animatsiyalargacha muzlaydi.
Buning sababi, JS "single-threaded"(shunga o'zbekcha nom topish kerak) va veb-sahifadagi barcha operatsiyalar o'sha thread'da bajariladi. Bunga HTML'ni taxlil qilinishi ham, CSS stillarni biriktirilish ham kiradi. Bularning barchasini esa hosdisalar sikli ("event loop") ma'lum ketma-ketlikda bajarilishini taminlaydi. Hodisalar sikli "call stack"ni, "callback queue"ni, DOMdagi o'rgarishlarni va boshqalarni kuzatib turadi. Ularning birortasida qilinadigan ish paydo bo'lsa, o'sha ishlar asosiy "thread"da bajariladi.
"Event loop" mavzusining o'zi ham juda katta va qiziq mavzu. Bu haqida ham keyinroq post yozaman.
π22