IlmHamroh
JavaScript Full-stack/8-qism. JavaScript asoslari19/61-dars22 daqiqa
Mundarija (40)

JavaScript bitwise operatorlari: &, |, ^, ~, siljitish va bit bayroqlar

Qisqacha: Bitwise (bitli) operatorlar sonni ikkilik ko'rinishda, ya'ni 0 va 1 lar qatori sifatida ko'radi va har bir bit ustida alohida ishlaydi. & (VA), | (YOKI), ^ (XOR), ~ (inkor) va <<, >>, >>> (siljitish) — shular. Ularning eng foydali ishi — bir nechta "ha/yo'q" belgini bitta sonda saqlash, masalan OQISH | YOZISH. Har kuni kerak bo'lmaydi, lekin kutubxonalar ichida va intervyularda uchraydi.

Bu darsda

  • Yetti bitwise operatorning har biri nima qilishini tushuntira olasiz.
  • Natijani ustun usulida qo'lda hisoblab, kod bilan tekshira olasiz.
  • JavaScript bitli amaldan oldin sonni 32 bitli butun songa aylantirishini bilasiz.
  • Bit bayroqlar bilan ruxsatlar tizimini yasay olasiz: qo'shish, tekshirish, olib tashlash.
  • ~~x va x | 0 hiylalari qachon aldashini taniysiz.

Oldin bilishingiz kerak: Nega 0 va 1: ikkilik sanoq sistemasi, Sonlar ichkarida: manfiy sonlar va bitli amallar, Arifmetik va tayinlash operatorlari, Operatorlar ustuvorligi.

1. Nega bu kerak?

Oldingi darsda JavaScript turlarni o'zi qanday o'zgartirishini ko'rdik. Endi sonlarga boshqa tomondan qaraymiz — ularning ichidagi bitlarga.

Tasavvur qiling: maktab uchun elektron jurnal yozyapsiz. Har bir foydalanuvchining uchta ruxsati bo'lishi mumkin:

  • o'qish — baholarni ko'rish (o'quvchi, ota-ona);
  • yozish — baho qo'yish (o'qituvchi);
  • o'chirish — noto'g'ri bahoni o'chirish (direktor).

Har ruxsat uchun alohida o'zgaruvchi ochish mumkin: oqishMumkin = true, yozishMumkin = false... Lekin ruxsatlar 20 ta bo'lsa-chi? Har foydalanuvchi uchun 20 ta true/false saqlaysiz.

Bitlar bilan esa hammasi bitta son ichiga sig'adi. Uydagi chiroq kalitlari qatorini tasavvur qiling: har bir kalit yoki yoqilgan, yoki o'chgan. Sondagi har bir bit — shunday bitta kalit.

Maslahat: Bu dars "ekotizim" qavatidan. Bitwise operatorlarni oddiy sayt yoki backend kodida kam yozasiz. Lekin ular kutubxonalar ichida, fayl ruxsatlarida, o'yinlarda va intervyu masalalarida uchraydi. Maqsad — ularni ko'rganda tanib, o'qiy olish. Hammasini yodlash shart emas.

2. Son ichidagi bitlar

2.1 Ikkilik ko'rinishni eslaymiz

Ikkilik sanoq sistemasi darsida ko'rgansiz: har qanday butun son — 0 va 1 lar qatori. O'ngdan chapga har bir o'rin qiymati ikki barobar oshadi: 1, 2, 4, 8, 16...

text
  13 = 8 + 4 + 0 + 1  →  1 1 0 1
  10 = 8 + 0 + 2 + 0  →  1 0 1 0
   5 = 0 + 4 + 0 + 1  →  0 1 0 1

JavaScript'da sonning ikkilik ko'rinishini ko'rish mumkin. Turlarni aniq o'zgartirish darsida .toString() ni o'rgangansiz. Qavs ichiga 2 bersangiz, u sonni ikkilik sanoqda yozib beradi:

js
const son = 13;

console.log(son.toString(2)); // 1101
console.log((10).toString(2)); // 1010

Ikkinchi qatorda son qavsga olingan. Qavssiz 10.toString(2) yozsangiz, JavaScript 10. ni kasr sonning boshi deb o'ylab chalkashadi. Sanoq tizimlari bilan ishlashni Son yozish shakllari darsida batafsil ko'ramiz.

2.2 Bitwise operator nima qiladi?

Bitwise operator (bitli operator) — ikki sonni ustma-ust qo'yib, bitlarini juft-juft solishtiradigan operator. Oddiy + sonni bir butun deb ko'radi. Bitwise operator esa uni kalitlar qatori deb ko'radi va har bir kalit ustida alohida amal bajaradi.

Yetti operator bor:

Operator Nomi Qisqacha
& VA (AND) Ikkala bit 1 bo'lsa — 1
| YOKI (OR) Kamida bittasi 1 bo'lsa — 1
^ XOR Bitlar har xil bo'lsa — 1
~ Inkor (NOT) Har bir bitni teskarisiga aylantiradi
<< Chapga siljitish Bitlarni chapga suradi
>> O'ngga siljitish Bitlarni o'ngga suradi, ishorani saqlaydi
>>> Nol bilan o'ngga siljitish O'ngga suradi, chapdan 0 kiritadi

Birma-bir ko'ramiz.

3. &, | va ^: bitlarni juft-juft solishtirish

3.1 Bitta bit uchun qoida

Avval eng kichik holat: ikkita bitta bit.

Bitlar & (VA) | (YOKI) ^ (XOR)
0 va 0 0 0 0
0 va 1 0 1 1
1 va 0 0 1 1
1 va 1 1 1 0
  • & — qat'iy: ikkalasi ham 1 bo'lsagina 1. Seyfni ochish uchun ikki kalit kerak bo'lgandek.
  • | — yumshoq: kamida bittasi 1 bo'lsa, 1. Uyga old eshikdan ham, orqa eshikdan ham kirsa bo'ladi.
  • ^ — XOR (exclusive OR, "istisno qiluvchi YOKI"): bitlar har xil bo'lsa 1, bir xil bo'lsa 0. Ikki qavatli uydagi zinapoya chirog'i: pastdagi yoki tepadagi kalitni bossangiz, chiroq holati o'zgaradi.

Bu jadval sizga tanish tuyulishi mumkin. Mantiqiy operatorlar darsidagi && va || ham xuddi shu mantiqda ishlaydi. Farqi — && butun qiymatga qaraydi, & esa har bir bitga alohida.

3.2 Ustun usulida hisoblash

Endi ikki butun sonni olamiz: 12 va 10. Ularni ustma-ust yozamiz va har ustunga jadvaldagi qoidani qo'llaymiz:

text
      12 = 1 1 0 0
      10 = 1 0 1 0
  -------------------
 12 & 10 = 1 0 0 0  →  8
 12 | 10 = 1 1 1 0  →  14
 12 ^ 10 = 0 1 1 0  →  6

Maktabdagi ustun usulida qo'shishga o'xshaydi, lekin "eslab qolish" (bir xonadan ikkinchisiga o'tkazish) yo'q. Har ustun o'zi alohida.

Kod bilan tekshiramiz:

js
console.log(12 & 10); // 8
console.log(12 | 10); // 14
console.log(12 ^ 10); // 6

Tekshirib ko'ring: 5 & 3 va 5 | 3 nechaga teng? (5 = 101, 3 = 011)

Javob

5 & 3 = 1: faqat eng o'ngdagi ustunda ikkala bit ham 1 (101 va 011 → 001).

5 | 3 = 7: har ustunda kamida bitta 1 bor (111), bu esa 4 + 2 + 1 = 7.

3.3 Natija har doim son

&& va || operandlardan birini qaytarishini eslaysiz. Bitli operatorlar esa har doim yangi son qaytaradi:

js
console.log(true & false); // 0
console.log(true | false); // 1
console.log("5" & 3); // 1

true bu yerda 1 ga, false esa 0 ga aylandi. "5" satri ham avval 5 soniga aylandi — bu yashirin coercion: bitli operator operandlarni doim songa o'giradi.

4. ~ — bitlarni teskarisiga aylantirish

4.1 Nima uchun ~5 manfiy?

~ (inkor, NOT) bitta son bilan ishlaydi: har bir 0 ni 1 ga, har bir 1 ni 0 ga aylantiradi.

js
console.log(~5); // -6
console.log(~0); // -1
console.log(~-1); // 0

Kutilmagan natija, to'g'rimi? 5 ning teskarisi 2 bo'ladi deb o'ylashingiz mumkin edi (101 → 010).

Sababi — ishora biti. Sonlar ichkarida darsida ko'rgansiz: manfiy sonlar ikkilik to'ldiruvchi (two's complement) usulida saqlanadi. Eng chapdagi bit — ishora: 0 bo'lsa musbat, 1 bo'lsa manfiy. Beshning chap tomonida aslida yana 29 ta nol bor. Inkor operatori ularni ham 1 ga aylantiradi — natijada eng chapdagi bit 1 bo'ladi va son manfiy chiqadi.

Hisoblashning qisqa formulasi bor: ~x har doim -x - 1 ga teng. Masalan, ~5 = -5 - 1 = -6.

Tekshirib ko'ring: ~10 nechaga teng?

Javob

-11. Formula bo'yicha: -10 - 1 = -11. Bitlarni o'zingiz teskari qilib chiqsangiz ham shu javob chiqadi, lekin formula ancha tez.

5. Siljitish operatorlari: <<, >>, >>>

5.1 << — chapga siljitish

a << n — a ning bitlarini n qadam chapga suradi. O'ng tomondan bo'sh joyga 0 lar kiradi:

text
  5      =     1 0 1
  5 << 1 =   1 0 1 0   →  10
  5 << 3 = 1 0 1 0 0 0 →  40

O'nlik sanoqda sonning oxiriga 0 qo'shsangiz, u 10 barobar oshadi. Ikkilikda esa har bir 0 sonni 2 barobar oshiradi:

js
console.log(5 << 1); // 10
console.log(5 << 3); // 40
console.log(1 << 4); // 16

5 << 3 — 5 * 2 * 2 * 2, ya'ni 5 * 8. Oxirgi qator esa muhim naqsh: 1 << n — ikkining n-darajasi. Bayroqlar yasashda aynan shu ishlatiladi.

5.2 >> — o'ngga siljitish

a >> n — bitlarni o'ngga suradi. O'ngdan "tushib ketgan" bitlar yo'qoladi. Natija — a ni 2**n ga bo'lib, kasr qismini tashlaganga o'xshaydi:

js
console.log(20 >> 2); // 5
console.log(25 >> 1); // 12
console.log(-20 >> 2); // -5
console.log(-9 >> 1); // -5

>> ishorani saqlaydi: chap tomondan ishora biti nusxalanadi. Shuning uchun manfiy son manfiyligicha qoladi.

Oxirgi qatorga e'tibor bering: -9 / 2 = -4.5, lekin natija -4 emas, -5. >> har doim kichik tomonga yaxlitlaydi. Manfiy sonlarda bu "noldan uzoqlashish" degani.

5.3 >>> — nol bilan o'ngga siljitish

>>> ham o'ngga suradi, lekin chapdan har doim 0 kiritadi. Musbat sonlarda u >> bilan bir xil. Manfiy sonlarda esa ishora biti 0 ga aylanadi va son birdan juda katta musbat songa aylanadi:

js
console.log(20 >>> 2); // 5
console.log(-20 >>> 2); // 1073741819
console.log(-1 >>> 0); // 4294967295

-1 ning 32 ta biti hammasi 1. >>> 0 ularni surmaydi, lekin "bu ishorasiz son" deb o'qiydi. Natija — 32 bitga sig'adigan eng katta son. x >>> 0 naqshini eski kutubxonalarda uchratasiz: u sonni 0 dan 4 294 967 295 gacha oraliqqa "o'raydi".

Tekshirib ko'ring: 3 << 2 va 40 >> 3 nechaga teng?

Javob

3 << 2 = 12: ikki qadam chapga — 2 marta ikkiga ko'paytirish, 3 * 4.

40 >> 3 = 5: uch qadam o'ngga — 3 marta ikkiga bo'lish, 40 / 8.

6. 32 bit qoidasi

6.1 Son vaqtincha 32 bitli butun songa aylanadi

Oddiy JavaScript sonlari ichkarida 64 bit egallaydi va kasr bo'la oladi. Bitli operatorlar esa boshqacha ishlaydi: amaldan oldin har bir operand 32 bitli ishorali butun songa aylantiriladi. Amal tugagach, natija yana oddiy son bo'ladi.

Bu aylantirishda ikki narsa yuz beradi:

  1. Kasr qismi tashlanadi. 3.7 → 3, -3.7 → -3.
  2. 32 bitga sig'maydigan qism kesiladi. Faqat o'ngdagi 32 ta bit qoladi.
js
console.log(3.7 | 0); // 3
console.log(-3.7 | 0); // -3
console.log(2147483647 | 0); // 2147483647
console.log(2147483648 | 0); // -2147483648
console.log(5000000000 | 0); // 705032704

x | 0 — "x ni hech qanday bit qo'shmasdan YOKI qil". Bitlar o'zgarmaydi, lekin 32 bitga aylantirish baribir bajariladi. Shuning uchun u aylantirishni ko'rsatish uchun qulay.

32 bitli ishorali son oralig'i: -2 147 483 648 dan 2 147 483 647 gacha. Bir birlik oshib ketsa, son "aylanib" manfiy tomonga o'tadi. Mashinaning spidometridagi probeg 999999 dan keyin 000000 ga qaytgandek.

6.2 Son bo'lmagan qiymatlar

Operand son bo'lmasa, avval songa aylantiriladi. Son chiqmasa (NaN), u 0 deb olinadi:

js
console.log(NaN | 0); // 0
console.log(undefined | 0); // 0
console.log("salom" | 0); // 0
console.log("12.9" | 0); // 12

Bu jim ishlaydi — hech qanday xato chiqmaydi. NaN birdan 0 bo'lib qolishi xavfli: noto'g'ri ma'lumot "to'g'ri" son qiyofasida yurib ketadi. Bu haqda "hiylalar" bo'limida yana gaplashamiz.

Diqqat: Siljitish miqdori ham 32 ga "o'raladi": 1 << 32 natijasi 1, chunki JavaScript faqat 0 dan 31 gacha qadam suradi (32 qadam → 0 qadam). Bitli operatorlar bilan 31-bitdan kattasiga chiqmang.

7. Bit bayroqlar: bitta sonda ko'p "ha/yo'q"

Endi darsning eng foydali qismi. Dars boshidagi elektron jurnalga qaytamiz.

7.1 Har ruxsatga bitta bit

Bit bayroq (bit flag) — sondagi bitta bit, u biror narsaning "yoqilgan" yoki "o'chirilgan"ini bildiradi. Bir nechta bayroq birga yozilgan son bitmask (bit niqob) deyiladi.

Har ruxsatga alohida bit ajratamiz. Buning uchun qiymatlar ikkining darajalari bo'lishi kerak: 1, 2, 4, 8...

js
const OQISH = 1; // 001
const YOZISH = 2; // 010
const OCHIRISH = 4; // 100

console.log(OQISH, YOZISH, OCHIRISH); // 1 2 4

Har bir sonning ikkilik ko'rinishida faqat bitta 1 bor va ular bir-birining joyiga tushmaydi. Shuning uchun ularni aralashtirib yuborish mumkin emas.

Nomlar katta harf bilan yozildi. Bu dasturchilar odati: "bu o'zgarmas sozlama, hech qachon o'zgarmaydi" degan belgi.

Maslahat: Bayroqlarni 1 << 0, 1 << 1, 1 << 2 ko'rinishida ham yozishadi. Natija bir xil (1, 2, 4), lekin qaysi bit ekanini raqamning o'zi aytib turadi: 1 << 5 — beshinchi o'rindagi bit.

7.2 Ruxsatlarni birlashtirish: |

Bir nechta ruxsatni bitta songa yig'ish uchun | ishlatiladi:

js
const OQISH = 1;
const YOZISH = 2;
const OCHIRISH = 4;

const oquvchi = OQISH;
const oqituvchi = OQISH | YOZISH;
const direktor = OQISH | YOZISH | OCHIRISH;

console.log(oquvchi); // 1
console.log(oqituvchi); // 3
console.log(direktor); // 7

Ustun usulida qarasak, | har ustunda kamida bitta 1 borligini tekshiradi:

text
  OQISH     = 0 0 1
  YOZISH    = 0 1 0
  -----------------
  oqituvchi = 0 1 1  →  3

3 soni o'z ichida "o'qish — ha, yozish — ha, o'chirish — yo'q" degan uchta javobni saqlayapti.

7.3 Ruxsatni tekshirish: &

"O'qituvchi baho qo'ya oladimi?" — buni & bilan bilamiz. oqituvchi & YOZISH faqat YOZISH bitini qoldiradi, qolganlarini 0 qiladi:

js
const OQISH = 1;
const YOZISH = 2;
const OCHIRISH = 4;
const oqituvchi = OQISH | YOZISH;

console.log(oqituvchi & YOZISH); // 2
console.log(oqituvchi & OCHIRISH); // 0

Natija 0 bo'lmasa — bit yoqilgan. 0 bo'lsa — o'chgan. true/false olish uchun !== 0 bilan solishtiramiz va natijani ternary bilan so'zga aylantiramiz:

js
const YOZISH = 2;
const OCHIRISH = 4;
const oqituvchi = 3;

const yozaOladi = (oqituvchi & YOZISH) !== 0;
const ochiraOladi = (oqituvchi & OCHIRISH) !== 0;

console.log(yozaOladi); // true
const javob = ochiraOladi ? "ruxsat bor" : "ruxsat yo'q";
console.log(javob); // ruxsat yo'q

Qavsga e'tibor bering: (oqituvchi & YOZISH). Bu qavs majburiy — nega ekanini "Ko'p uchraydigan xatolar" bo'limida ko'ramiz.

7.4 Qo'shish, olib tashlash, almashtirish

Bitli operatorlarning ham qisqa tayinlash shakllari bor: |=, &=, ^=, <<=, >>=. Ular += kabi ishlaydi: a |= b — bu a = a | b.

js
const OQISH = 1;
const YOZISH = 2;
const OCHIRISH = 4;

let ruxsat = OQISH;

ruxsat |= YOZISH; // yozishni qo'shamiz
console.log(ruxsat); // 3

ruxsat |= OCHIRISH; // o'chirishni qo'shamiz
console.log(ruxsat); // 7

ruxsat &= ~YOZISH; // yozishni olib tashlaymiz
console.log(ruxsat); // 5

ruxsat ^= OCHIRISH; // o'chirishni almashtiramiz
console.log(ruxsat); // 1

Uchta naqshni eslab qoling:

Ish Kod Nega ishlaydi
Yoqish r |= B | bitni 1 ga aylantiradi, boshqalariga tegmaydi
O'chirish r &= ~B ~B da faqat shu bit 0, & uni o'chiradi
Almashtirish r ^= B ^ bitni teskarisiga o'giradi

O'chirish naqshini batafsil ko'raylik. YOZISH = 010, demak ~YOZISH = ...101 (faqat o'rtadagi bit 0). 7 & ~YOZISH: 111 & 101 = 101 = 5. Yozish o'chdi, qolgan ikkitasi joyida qoldi.

Qisman yechilgan misol. Ota-onaga (ruxsat = 1) yozish ruxsatini qo'shish uchun ruxsat YOZISH yoziladi. Direktordan (ruxsat = 7) o'chirish ruxsatini olish uchun esa ruxsat &= yoziladi.

7.5 Bir nechta ruxsatni birdan tekshirish

"Bu odamda o'qish va yozish ruxsati bormi?" Ikkalasini bitta niqobga yig'amiz va natija niqobning o'ziga tengligini tekshiramiz:

js
const OQISH = 1;
const YOZISH = 2;
const direktor = 7;
const oquvchi = 1;

const kerak = OQISH | YOZISH; // 3

console.log((direktor & kerak) === kerak); // true
console.log((oquvchi & kerak) === kerak); // false
console.log((oquvchi & kerak) !== 0); // true
  • === kerak — "hamma kerakli bit yoqilganmi?"
  • !== 0 — "kamida bittasi yoqilganmi?"

O'quvchida faqat o'qish bor. Shuning uchun "hammasi" savoliga false, "kamida bittasi" savoliga true chiqdi.

Tekshirib ko'ring: let r = 6; (yozish + o'chirish). r &= ~4; dan keyin r nechaga teng va unda qaysi ruxsat qoladi?

Javob

2 — faqat yozish qoladi. 6 = 110, ~4 ning oxirgi uch biti 011. 110 & 011 = 010 = 2. ~4 faqat o'chirish bitini 0 qildi, & esa uni r dan olib tashladi.

8. Hiylalar: ~~x, x | 0 va n & 1

Internetdagi kodlarda bitli operatorlarni "qisqa yo'l" sifatida ishlatishadi. Ularni tanishingiz kerak, lekin ehtiyotkorlik bilan.

8.1 ~~x va x | 0 — kasr qismini tashlash

~ ni ikki marta qo'llasangiz, son o'ziga qaytadi. Lekin 32 bitga aylantirish baribir bajariladi — kasr qismi tushib qoladi. x | 0 ham xuddi shunday:

js
console.log(~~7.9); // 7
console.log(7.9 | 0); // 7
console.log(~~-4.7); // -4
console.log(~~"12.5"); // 12

Qisqa va tez ko'rinadi. Lekin uchta tuzog'i bor:

js
console.log(~~3000000000); // -1294967296
console.log(~~NaN); // 0
console.log(~~"salom"); // 0
  1. Katta sonlar buziladi. 2 147 483 647 dan katta son 32 bitga sig'maydi va butunlay boshqa songa aylanadi. Summalar, telefon raqamlari, vaqt (millisekundlarda) — hammasi shu chegaradan oshadi.
  2. Xato yashirinadi. NaN jimgina 0 ga aylanadi. Formadan "abc" kelsa, dastur uni 0 deb qabul qiladi.
  3. O'qish qiyin. ~~x ni ko'rgan har kim bir soniya to'xtab o'ylaydi.

Kasr qismini tashlash uchun maxsus funksiya bor — Math.trunc(x). U katta sonlarda ham to'g'ri ishlaydi va nima qilayotgani nomidan ko'rinadi. Uni Math obyekti darsida o'rganamiz.

Diqqat: ~~ va | 0 ni faqat kichik butun sonlar ekaniga aniq ishonchingiz komil bo'lganda ishlating (masalan, o'yindagi piksel koordinatasi). Pul, ID va sanalar uchun — hech qachon.

8.2 n & 1 — juft yoki toq?

Sonning eng o'ngdagi biti 1 bo'lsa — son toq, 0 bo'lsa — juft. Shuning uchun n & 1 juft-toqni aniqlaydi:

js
console.log(7 & 1); // 1
console.log(10 & 1); // 0
console.log(-3 & 1); // 1
console.log(-3 % 2); // -1

Arifmetik operatorlar darsida juft-toqni % 2 bilan tekshirgan edik. Oxirgi ikki qatordagi farqqa qarang: manfiy toq sonda % 2 natijasi -1, & 1 esa doim 1. Shuning uchun n % 2 === 1 manfiy sonlarda aldaydi. n % 2 !== 0 yoki (n & 1) === 1 esa har doim to'g'ri.

8.3 Eski kodda uchraydigan ~ hiylasi

Eski kodlarda ~matn.indexOf("...") ga o'xshash yozuvni ko'rishingiz mumkin. U ~-1 = 0 ekanidan foydalanadi: "topilmadi" javobi falsy bo'lib qoladi. Bugun buning o'rniga aniq nomli metod bor. Uni Matn ichida qidirish darsida ko'ramiz — hozir faqat "bunaqa narsa bor ekan" deb eslab qo'ying.

9. Ko'p uchraydigan xatolar

9.1 ^ ni daraja deb o'ylash

Matematikada 2^3 — "ikkining kubi". Ko'p dasturchi JavaScript'da ham shunday yozadi:

js
console.log(2 ^ 3); // 1
console.log(2 ** 3); // 8

Xato chiqmaydi, lekin natija noto'g'ri. ^ — XOR: 10 ^ 11 = 01 = 1. Darajaga ko'tarish uchun ** ishlatiladi.

9.2 & ni && o'rnida yozish

js
const kirgan = true;
const tolagan = false;

console.log(kirgan && tolagan); // false
console.log(kirgan & tolagan); // 0

Bitta & mantiqiy qiymat emas, son qaytaradi. Bundan tashqari u qisqa tutashuv qilmaydi — o'ng tomonni har doim hisoblaydi. Shartlarda doim && va || yozing.

9.3 Qavssiz tekshirish

Bu eng xavfli xato, chunki natija ba'zan to'g'ri chiqib, sizni aldaydi:

js
const YOZISH = 2;
const oquvchi = 1; // faqat o'qish

console.log(oquvchi & YOZISH !== 0); // 1
console.log((oquvchi & YOZISH) !== 0); // false

O'quvchida yozish ruxsati yo'q, lekin birinchi qator 1 — truthy qiymat berdi! Sababi — ustuvorlik. !== operatori & dan kuchliroq. JavaScript birinchi qatorni shunday o'qidi:

text
oquvchi & (YOZISH !== 0)  →  1 & true  →  1 & 1  →  1

Bitli operatorlar ustuvorlik jadvalida taqqoslash va tenglikdan pastda turadi. Qoida: &, |, ^ ni boshqa operator bilan aralashtirganda har doim qavs qo'ying.

Qiziqish uchun, ularning jadvaldagi o'rni:

  • ~ — boshqa unar operatorlar (!, typeof) bilan bir qatorda;
  • <<, >>, >>> — + / - dan keyin, < / > dan oldin;
  • &, keyin ^, keyin | — === dan keyin, && dan oldin.

9.4 |= va ||= ni adashtirish

Ular bir-biriga juda o'xshaydi, lekin butunlay boshqa ish qiladi:

js
let a = 4;
a ||= 1;
console.log(a); // 4

let b = 4;
b |= 1;
console.log(b); // 5

a ||= 1 — "a falsy bo'lsa, 1 yoz" (mantiqiy tayinlash). 4 truthy, shuning uchun a o'zgarmadi. b |= 1 esa bitni yoqadi: 100 | 001 = 101 = 5.

9.5 Bayroqqa ikkining darajasi bo'lmagan son berish

js
const OQISH = 1;
const YOZISH = 2;
const OCHIRISH = 3; // ❌ 3 = 011 — bu OQISH | YOZISH

const ruxsat = OQISH;
console.log((ruxsat & OCHIRISH) !== 0); // true

O'quvchida faqat o'qish bor, lekin dastur "o'chira oladi" dedi. 3 sonining ikkita biti yoqilgan va ulardan biri OQISH bilan ustma-ust tushdi. Bayroq qiymatlari faqat 1, 2, 4, 8, 16... bo'lishi kerak. Adashmaslik uchun 1 << n shaklida yozing.

10. Mashqlar

1-mashq (oson): Qo'lda hisoblang

6 = 110, 3 = 011. Avval qog'ozda ustun usulida hisoblang, keyin kod bilan tekshiring:

  • 6 & 3
  • 6 | 3
  • 6 ^ 3
  • 6 << 2
Yechim
js
console.log(6 & 3); // 2
console.log(6 | 3); // 7
console.log(6 ^ 3); // 5
console.log(6 << 2); // 24
  • 110 & 011 = 010 = 2 — faqat o'rta ustunda ikkala bit ham 1.
  • 110 | 011 = 111 = 7 — har ustunda kamida bitta 1.
  • 110 ^ 011 = 101 = 5 — birinchi va uchinchi ustunda bitlar har xil.
  • 6 << 2 = 11000 = 24 — ikki qadam chapga, ya'ni 6 * 4.

2-mashq (o'rta): Taksi buyurtmasi

Taksi ilovasida mijoz qo'shimcha xizmatlarni tanlaydi. Quyidagi bayroqlarni e'lon qiling (qiymatlarni 1 << n bilan yozing):

  • KONDITSIONER — 0-bit;
  • BOLA_ORINDIGI — 1-bit;
  • BAGAJ — 2-bit;
  • UY_HAYVONI — 3-bit.

So'ng:

  1. buyurtma o'zgaruvchisiga konditsioner va bagajni yozing, uni konsolga chiqaring.
  2. Buyurtmada bola o'rindig'i bormi — true/false chiqaring.
  3. Mijoz fikrini o'zgartirdi: bagajni olib tashlang, uy hayvonini qo'shing. Yangi qiymatni chiqaring.

Ishora: qo'shish — |=, olib tashlash — &= ~, tekshirish — (x & B) !== 0.

Yechim
js
const KONDITSIONER = 1 << 0; // 1
const BOLA_ORINDIGI = 1 << 1; // 2
const BAGAJ = 1 << 2; // 4
const UY_HAYVONI = 1 << 3; // 8

let buyurtma = KONDITSIONER | BAGAJ;
console.log(buyurtma); // 5

console.log((buyurtma & BOLA_ORINDIGI) !== 0); // false

buyurtma &= ~BAGAJ;
buyurtma |= UY_HAYVONI;
console.log(buyurtma); // 9

5 = 0101 — konditsioner (1) va bagaj (4). Bagajni olib tashlasak 0001 qoladi. Uy hayvonini qo'shsak 1001 = 9 bo'ladi.

3-mashq (qiyin): Umumiy bo'sh kun

Ali va Malika birga futbolga bormoqchi. Haftaning har kuni — bitta bit: dushanba — 0-bit, seshanba — 1-bit, chorshanba — 2-bit, payshanba — 3-bit, juma — 4-bit, shanba — 5-bit, yakshanba — 6-bit.

  • Ali bo'sh: dushanba, chorshanba, juma, shanba.
  • Malika bo'sh: seshanba, juma, shanba, yakshanba.

Topshiriq:

  1. Yetti kun uchun bayroqlarni e'lon qiling (DU, SE, CHOR, PAY, JU, SHAN, YAK).
  2. ali va malika niqoblarini yasang.
  3. umumiy — ikkalasi ham bo'sh kunlar. Uni hisoblang va chiqaring.
  4. Jumada birga bora oladimi? Dushanbada-chi?
  5. Bonus: haftaning qaysi kunida hech kim bo'sh emas? Ishora: kamida bittasi bo'sh kunlarni | bilan toping, keyin ~ bilan teskarisiga o'giring. ~ 32 bitning hammasini aylantiradi, shuning uchun natijani 7 ta kun niqobi (127 = 1111111) bilan & qiling.
Yechim
js
const DU = 1 << 0;
const SE = 1 << 1;
const CHOR = 1 << 2;
const PAY = 1 << 3;
const JU = 1 << 4;
const SHAN = 1 << 5;
const YAK = 1 << 6;

const ali = DU | CHOR | JU | SHAN;
const malika = SE | JU | SHAN | YAK;

const umumiy = ali & malika;
console.log(umumiy); // 48

console.log((umumiy & JU) !== 0); // true
console.log((umumiy & DU) !== 0); // false

const hafta = 127;
const hechKim = ~(ali | malika) & hafta;
console.log(hechKim === PAY); // true
  • ali = 53, malika = 114. & faqat ikkala niqobda ham yoqilgan bitlarni qoldiradi: JU | SHAN = 16 + 32 = 48.
  • ali | malika = 119 — kamida bittasi bo'sh kunlar. Unda faqat payshanba (8) yo'q.
  • ~119 barcha 32 bitni aylantiradi, & 127 esa faqat hafta kunlarining 7 bitini qoldiradi. Natija — 8, ya'ni payshanba.

& — ikki to'plamning umumiy qismi, | — ularning birlashmasi. Bitmask'lar aslida shunday kichik "to'plamlar".

11. Real ishda

  • Linux fayl ruxsatlari. Terminal darslaridagi chmod 755 aynan bitmask: o'qish = 4, yozish = 2, bajarish = 1. 7 = 4 + 2 + 1 — hammasi ruxsat, 5 = 4 + 1 — o'qish va bajarish.
  • Kutubxonalar ichida. React (sayt yasash uchun mashhur kutubxona, kursda alohida qism bor) ichki kodida komponent holatlarini bit bayroqlar bilan saqlaydi. Discord botlarida ham ruxsatlar bitta katta son sifatida keladi.
  • Rang bilan ishlash. #ff8800 kabi rangdan qizil, yashil, ko'k qismini ajratish — >> va & bilan.
  • Binar ma'lumot. Fayl, rasm va tarmoq baytlari bilan ishlashda bitli amallar kerak bo'ladi — typed arrays darsida qaytamiz.
  • Intervyu. "n & 1 nima qiladi?", "sonning 2 ning darajasi ekanini qanday tekshirasiz?" kabi savollar beriladi. Ularga bit manipulyatsiya masalalari darsida tayyorlanamiz.

Xulosa

  • Bitli operatorlar sonni bitlar qatori deb ko'radi va har bir bit ustida alohida ishlaydi.
  • & — ikkalasi 1 bo'lsa, | — kamida bittasi 1 bo'lsa, ^ — har xil bo'lsa 1. ~x = -x - 1.
  • << — 2 ga ko'paytirish, >> — 2 ga bo'lib pastga yaxlitlash, >>> — chapdan 0 kiritadi.
  • Amaldan oldin son 32 bitli butun songa aylanadi: kasr tashlanadi, katta son buziladi, NaN → 0.
  • Bayroqlar: yoqish r |= B, o'chirish r &= ~B, tekshirish (r & B) !== 0 — qavs bilan!
  • ~~x va x | 0 o'rniga Math.trunc(x); ^ — daraja emas, daraja — **.

Keyingi dars: String asoslari: yozish, indeks, o'zgarmaslik — sonlardan matnga o'tamiz: satrni yozish usullari, belgilarni indeks bilan o'qish va nega satrni "joyida" o'zgartirib bo'lmasligini ko'ramiz.

Ulashish:Telegram'da

Izohlar (0)

Izoh yozish uchun kiring.

  • Hozircha izoh yo'q. Birinchi bo'ling!
JavaScript bitwise operatorlari: &, |, ^, ~, siljitish va bit bayroqlar — IlmHamroh