Операции с битами не очень распространены в JavaScript, но бывает, что без них не обойтись

Чтобы понять, как работают побитовые операции в JS, тебе нужны 2 вещи:

  • разобраться в том, что такое двоичная (бинарная) система счисления
  • как переводить числа из десятичной системы в двоичную и обратно

Ответы на эти вопросы и введение ты можешь найти тут.

Обзор всех побитовых операций в JavaScript

Оператор Название Описание
& И Если оба бита равны 1 - результат 1. Если хотя бы один из них 0, то и результат 0.
` ` ИЛИ
^ Исключающее ИЛИ (XOR) Если оба бита одинаковые - результат 0. Если биты разные, то результат - 1.
~ НЕ Инвертирует все биты в числе. Нули становятся единицами, а единицы - нулями.
<< Сдвиг влево Сдвигает все биты влево, заполняет пустые слоты нулями.
>> Знаковый сдвиг вправо Сдвигает все биты вправо, заполняет пусты слоты значением самого левого бита числа. Таким образом знак числа не меняется.
>>> Беззнаковый сдвиг вправо Сдвигает все биты вправо, заполняет пустые слоты нулями.

Примеры и использование

Побитовые операторы в JavaScript будет сложно понять, если применять их к десятичным числам.

Советую взять лист бумаги, карандаш и начать с того, чтобы перевести все десятичные числа из примеров в их двоичное представление.

Операторы И, ИЛИ, XOR

Операторам &, | и ^ требуется 2 числа, чтобы правильно работать. Они сравнивают биты в числах по одному используя правила из таблицы выше.

Давай попробуем их применить. Двоичное представление чисел записано справа в комментариях:

const x = 5;   // 0101
const y = 6;   // 0110

Будет проще считать, если ты запишешь двоичные числа в столбик. Вот так:

И   0101    ИЛИ 0101     XOR 0101
    0110        0110         0110
    ----        ----         ----
    0100        0111         0011

Сейчас, мы добавим console.log и проверим, правильно ли мы посчитали:

console.log(x & y);  // 4
console.log(x || y); // 7
console.log(x ^ y);  // 3

Важная особенность XOR в том, что, если ты с обеих сторон оператора напишешь одно и то же число, то в итоге всегда получишь ноль.

console.log(x ^ x);  // 0
console.log(y ^ y);  // 0

С другой стороны, если заменишь ^ на & или |, то число не изменится

Оператор НЕ

Оператор ~ работает иначе. Он называется унарным оператором и применяется к одному числу.

НЕ 0101 => 1010
НЕ 0110 => 1001
console.log(~x);     // -6
console.log(~y);     // -7

Знаковый бит тоже меняется, так как он определяется самым левым битом в JavaScript числах. Если он равен 0, то число положительное, 1 - отрицательное.

Если ты применишь оператор ~ дважды к одному и тому же числу, то ты вернешься туда, откуда начал:

console.log(~~x);     // 5

Операторы побитового сдвига

Операторам побитового сдвига нужно 2 числа. Первое — само число, биты которого мы будем двигать. Второе — количество двоичных разрядов на которое будет выполнен сдвиг.

Сдвиг влево

Сдвинуть двоичное число на 1 разряд влево — это то же самое, что умножить его на два. Исключение — большие числа, которые после умножения не поместятся в памяти.

console.log(x << 1);   // 10
console.log(y << 2);   // 24

Сдвиг вправо

Правый сдвиг, в отличие от левого, делает числа меньше. Если число достаточно большое, то это будет эквивалентно делению на два. В нашем случае, с маленькими числами, все не так просто:

console.log(x >> 1);   // 2
console.log(y >> 2);   // 1

Не ленись, бери карандаш и проверь расчеты самостоятельно!

Беззнаковый сдвиг вправо

Беззнаковый сдвиг вправо отличается тем, что он не сохраняет знаковый бит (самый левый). Когда он применяется к отрицательным числам, то они станут положительными, потому что все пустые места будет заполнены нулями.

const n = 100;   
const m = -100;

console.log(n >>> 2);   // 25
console.log(m >>> 2);   // 1073741799

Не удивительно, что мы сдвинули 100 на 2 бита вправо и получили число в 4 раза меньше.

Но ты понимаешь почему -100 превратилось в 1073741799?

Выводы

Если ты занимаешься веб разработкой, то тебе, скорее всего, нечасто придется сталкиваться с побитовыми операциями в JavaScript.

С другой стороны, если ты ищешь работу и ходишь по собеседованиям, то это одна из любимых тем “на засыпку”. Многие задачи решаются очень красиво с помощью побитовых операций. Например, определить является ли число четным.

Если ты готовишься к собеседованиям, попробуй мобильное приложение Coderslang. В нем более 1500 вопросов по JavaScript, HTML/CSS, Java, C#, Node.js, React.js, React Native, и QA. Скачать можно на iOS и Android.