Вирази та оператори

Цей розділ описує вирази та оператори JavaScript, включно з операторами присвоєння, порівняння, арифметичними, бітовими, логічними, рядковими, тернарним і так далі.

На високому рівні, вираз – це дійсна одиниця коду, що обчислюється до значення. Є два типи виразів: ті, котрі мають побічні ефекти (як то присвоєння значень), і ті, котрі суто обчислюються.

Вираз x = 7 є прикладом першого типу. Цей вираз вживає оператор = для присвоєння змінній x значення семи. Сам вираз обчислюється в 7.

Вираз 3 + 4 є прикладом другого типу. Цей вираз вживає оператор + для додавання 3 і 4 докупи й вироблення значення 7. Проте якщо такий вираз не є частиною більшої конструкції (наприклад, оголошення змінної виду const z = 3 + 4), то його результат буде негайно відкинутий; зазвичай це буває помилкою програміста, адже обчислення не виробляє жодних ефектів.

Як показують приклади вище, усі складні вирази об'єднуються операторами, як то = і +. У цій частині – знайомство з наступними операторами:

Ці оператори об'єднують операнди, котрі або сформовані операторами вищого пріоритету, або одним із базових виразів. Повний і розгорнутий список операторів та виразів доступний також у довіднику.

Пріоритет операторів визначає порядок, в якому вони застосовуються при обчисленні виразу. Наприклад:

const x = 1 + 2 * 3;
const y = 2 * 3 + 1;

Попри те, що * і + зустрічаються в різному порядку, обидва вирази дадуть 7, тому що * має пріоритет над +, тож поєднаний * вираз завжди буде обчислений першим. Пріоритет операторів можна відкинути за допомогою дужок (що утворює згрупований вираз — один з базових виразів). Повну таблицю пріоритетів операторів, а також різні каверзи – шукайте на сторінці Довідки пріоритету операторів.

JavaScript має і бінарні, і унарні оператори, а також один особливий тернарний оператор – умовний оператор. Бінарний оператор вимагає двох операндів, одного перед оператором і одного після:

operand1 operator operand2

Наприклад, 3 + 4 або x * y. Така форма зветься інфіксним бінарним оператором, тому що оператор розміщений між двома операндами. Усі бінарні оператори в JavaScript є інфіксними.

Унарні оператори вимагають одного операнда – або перед, або після оператора:

operator operand
operand operator

Наприклад, x++ або ++x. Форма operator operand зветься префіксним унарним оператором, а форма operand operatorпостфіксним унарним оператором. ++ і -- – єдині постфіксні оператори в JavaScript; уся решта операторів, як то !, typeof тощо, – є префіксними.

Оператори присвоєння

Оператор присвоєння присвоює значення своєму лівому операндові на основі значення правого операнда. Простий оператор присвоєння – це знак дорівнює(=), він присвоює значення свого правого операнда лівому операндові. Тобто x = f() – це вираз присвоєння, котрий присвоює значення f() змінній x.

Крім нього, є складені оператори присвоєння, котрі є скороченнями операцій, перелічених у наступній таблиці:

Присвоєння властивостям

Якщо вираз обчислюється до об'єкта, то ліва сторона виразу присвоєння може виконувати присвоєння властивостям цього виразу. Наприклад:

const obj = {};

obj.x = 3;
console.log(obj.x); // Виводить 3.
console.log(obj); // Виводить { x: 3 }.

const key = "y";
obj[key] = 5;
console.log(obj[key]); // Виводить 5.
console.log(obj); // Виводить { x: 3, y: 5 }.

Більше інформації про об'єкти – в Роботі з об'єктами.

Якщо вираз не обчислюється до об'єкта, то присвоєння властивостям такого виразу – не виконуються.

const val = 0;
val.x = 3;

console.log(val.x); // Виводить undefined.
console.log(val); // Виводить 0.

У суворому режимі код вище викидає помилку, тому що не можна присвоювати властивості примітивам.

Є помилкою присвоєння значень незмінним властивостям або властивостям виразів без властивостей (null і undefined).

Деструктурування

Корисний для складних присвоєнь синтаксис присвоєння з деструктуруванням – це вираз JavaScript, котрий дає змогу видобути дані з масивів та об'єктів за допомогою синтаксису, котрий є дзеркальним відображенням конструювання масивів та об'єктних літералів.

Без деструктурування для видобуття з масивів і об'єктів кількох значень необхідні кілька інструкцій:

const foo = ["один", "два", "три"];

// без деструктурування
const one = foo[0];
const two = foo[1];
const three = foo[2];

Завдяки деструктуруванню можна видобувати кілька значень в окремі змінні за допомогою однієї інструкції:

const [one, two, three] = foo;

Обчислення та вкладеність

Загалом, присвоєння вживаються в межах оголошень змінних (тобто вкупі з const, let чи var) або ж як окремі інструкції).

// Оголошується змінна x, а потім ініціалізується результатом f().
// Результат виразу присвоєння x = f() – відкидається.
let x = f();

x = g(); // Повторно присвоює змінній x результат g().

А проте, подібно до інших виразів, вирази присвоєння виду x = f() обчислюються до значення результату. Хоч зазвичай цей результат не використовується, він може бути використаний іншим виразом.

Утворення ланцюжків присвоєнь або присвоєнь, вкладених в інші вирази, може призвести до неочікуваної поведінки. Через це частина посібників зі стилю JavaScript коду не радить утворювати з присвоєнь ланцюжки або вкладеність. Попри це, іноді ланцюжки та вкладеність присвоєнь можуть траплятися, тому важливо розуміти, як вони працюють.

При додаванні присвоєння в ланцюжок або вкладеність, результат такого присвоєння сам може бути присвоєний іншій змінній. Він може бути виведений, вписаний в літерал масиву або виклик функції, і так далі.

let x;
const y = (x = f()); // Або рівносильне: const y = x = f();
console.log(y); // Виводить повернене значення присвоєння x = f().

console.log(x = f()); // Безпосередньо виводить повернене значення.

// Вираз присвоєння може бути вкладений в будь-якому місці,
// в якому вирази загалом дозволені,
// як то елементи літералів масивів або аргументи викликів функцій.
console.log([0, x = f(), 0]);
console.log(f(0, x = f(), 0));

Результат обчислення відповідає виразові справа від знака = у колонці "Значення" таблиці вище. Це означає, що x = f() обчислюється в те, чим є результат f(), x += f() обчислюється в суму x + f(), x **= f() обчислюється в піднесення до степеня x ** f(), і так далі.

Що до логічних присвоєнь, x &&= f(), x ||= f() і x ??= f(), то повернене значення – значення логічної операції без присвоєння, тобто x && f(), x || f() та x ?? f() відповідно.

При утворенні ланцюжків з таких виразів без дужок, або інакшого групування операторів – наприклад, в літералах масивів, вирази присвоєння групуються справа наліво (вони мають праву асоціативність), але обчислюються зліва направо.

Зверніть увагу на те, що для всіх операторів присвоєння, крім самого =, результівне значення – завжди засноване на значеннях операндів до операції.

Наприклад, оголошені такі функції – f і g, а також змінні x та y:

function f() {
  console.log("F!");
  return 2;
}
function g() {
  console.log("G!");
  return 3;
}
let x, y;

Погляньте на ці три приклади:

y = x = f();
y = [f(), x = g()];
x[f()] = g();

Приклад обчислення №1

Запис y = x = f() – рівносильний щодо y = (x = f()), адже оператор присвоєння = має праву асоціативність. Проте обчислюється він зліва направо:

  1. Починається обчислення виразу присвоєння y = x = f().
    1. y зліва цього присвоєння обчислюється в посилання на змінну y.
    2. Починається обчислення виразу x = f().
      1. x зліва цього присвоєння обчислюється в посилання на змінну x.
      2. Виклик функції f() виводить у консоль "F!", а тоді обчислюється в число 2.
      3. Цей результат 2 з f() – присвоюється x.
    3. Вираз присвоєння x = f() завершив виконання; його результат став новим значенням x, а саме – 2.
    4. Цей результат 2 й собі присвоюється y.
  2. Вираз присвоєння y = x = f() завершив виконання; його результат став новим значенням y – котре виявилося 2. x і y присвоєно значення 2, а консоль вивела "F!".

Приклад обчислення №2

y = [ f(), x = g() ] так само обчислюється зліва направо:

  1. Починається обчислення виразу присвоєння y = [ f(), x = g() ].
    1. y зліва цього присвоєння обчислюється в посилання на змінну y.
    2. Починається обчислення вбудованого літерала масиву [ f(), x = g() ].
      1. Виклик функції f() виводить у консоль "F!", а тоді обчислюється в число 2.
      2. Починається обчислення виразу присвоєння x = g().
        1. x зліва цього присвоєння обчислюється в посилання на змінну x.
        2. Виклик функції g() виводить у консоль "G!" , а тоді обчислюється в число 3.
        3. Цей результат 3 з g() – присвоюється x.
      3. Вираз присвоєння x = g() завершив виконання; його результат став новим значенням x, а саме – 3. Це результівне 3 стає новим елементом вбудованого літерала масиву (після 2 з f()).
    3. Вбудований літерал масиву [ f(), x = g() ] завершив виконання; його результат – масив з двома значеннями: [ 2, 3 ].
    4. Цей масив [ 2, 3 ] присвоюється y.
  2. Вираз присвоєння y = [ f(), x = g() ] завершив виконання; його результат стає новим значенням y – котре виявилося [ 2, 3 ]. Таким чином, x присвоєно 3, y присвоєно [ 2, 3 ], а консоль вивела "F!", а потім "G!".

Приклад обчислення №3

Вираз x[f()] = g() так само обчислюється зліва направо. (Цей приклад виходить з припущення, що x уже присвоєний якийсь об'єкт. Більше про об'єкти читайте в Роботі з об'єктами.)

  1. Починається обчислення виразу x[f()] = g().
    1. Починається обчислення звертання до властивості x[f()] зліва цього присвоєння.
      1. x у цьому звертанні до властивості обчислюється в посилання на змінну x.
      2. Потім виклик функції f() виводить "F!" у консоль і обчислюється в число 2.
    2. Звертання до властивості x[f()] у цьому присвоєнні завершує виконання; його результатом є посилання на змінну властивість: x[2].
    3. Потім виклик функції g() виводить "G!" у консоль, а тоді обчислюється в число 3.
    4. Тепер 3 присвоюється x[2]. (Цей крок має успіх лише за умови того, що x присвоєно об'єкт.)
  2. Вираз присвоєння x[f()] = g() завершує виконання; його результатом є нове значення x[2], а саме – 3. Тепер x[2] присвоєно 3, а консоль вивела "F!", і потім – "G!".

Слід уникати ланцюжків присвоєння

Ланцюжки присвоєнь і вкладання присвоєнь в інші вирази можуть призводити до дивної поведінки. Через це заведено уникати ланцюжків присвоєння в межах однієї інструкції.

Якщо конкретніше, то постановка ланцюжка змінних в інструкціях const, let і var нерідко не працює. Лише зовнішня (найлівіша) змінна оголошується; решта змінних в межах такого ланцюжка присвоєння не оголошуються інструкцією const, let чи var. Наприклад:

const z = y = x = f();

Ця інструкція нібито оголошує змінні x, y і z. Проте фактично вона оголошує лише z. y і x є або недійсними посиланнями на відсутні змінні (в суворому режимі) або, що іще гірше, призводять до неявного створення глобальних змінних x і y, коли в недбалому режимі.

Оператори порівняння

Оператор порівняння порівнює свої операнди й повертає логічне значення, засноване на тому, чи є істинним порівняння. Операнди можуть бути числовими, рядковими, логічними або об'єктними значеннями. Рядки порівнюються на основі стандартного лексикографічного порядку, за допомогою значень Unicode. У більшості випадків, якщо два операнди мають різні типи, то JavaScript намагається перетворити їх до відповідного типу задля порівняння. Ця поведінка загалом призводить до числового порівняння операндів. Єдиний виняток щодо перетворень типів при порівнянні включає оператори === і !==, які виконують порівняння строгої рівності й строгої нерівності. Ці оператори не намагаються перетворити операнди до сумісних типів перед їх порівнянням. Наступна таблиця описує оператори порівняння відносно такого коду:

const var1 = 3;
const var2 = 4;
Оператори порівняння
Оператор Опис Приклади, що повертають true
Рівності (==) Повертає true, якщо операнди дорівнюють одне одному. 3 == var1

"3" == var1

3 == '3'
Нерівності (!=) Повертає true, якщо операнди не дорівнюють одне одному. var1 != 4
var2 != "3"
Строгої рівності (===) Повертає true, якщо операнди дорівнюють одне одному й мають один і той же тип. Дивіться також Object.is і тотожність у JS. 3 === var1
Строгої нерівності (!==) Повертає true, якщо операнди належать до одного типу, але не дорівнюють одне одному, або належать до різних типів. var1 !== "3"
3 !== '3'
Більше (>) Повертає true, якщо лівий операнд більший за правий. var2 > var1
"12" > 2
Більше або дорівнює (>=) Повертає true, якщо лівий операнд більший або дорівнює правому. var2 >= var1
var1 >= 3
Менше (<) Повертає true, якщо лівий операнд менший за правий. var1 < var2
"2" < 12
Менше або дорівнює (<=) Повертає true, якщо лівий операнд менший або дорівнює правому. var1 <= var2
var2 <= 5

Примітка: => – це не оператор порівняння, а запис у стрілкових функціях.

Арифметичні оператори

Арифметичні оператори приймають як операнди числові значення (або літерали, або змінні), а повертають – єдине числове значення. Стандартні арифметичні операції – це додавання (+), віднімання (-), множення (*) та ділення (/). Ці оператори працюють так, як і в більшості решти мов програмування, коли застосовуються до дробових чисел (а саме, зверніть увагу на те, що ділення на нуль повертає нескінченність). Наприклад:

1 / 2; // 0.5
1 / 2 === 1.0 / 2.0; // це істинно

На додачу до стандартних арифметичних операцій (+, -, *, /), JavaScript пропонує арифметичні операції, перелічені в наступній таблиці:

Арифметичні операції
Оператор Опис Приклад
Остача від ділення (%) Бінарний оператор. Повертає ціле число, котре є остачею від ділення двох операндів. 12 % 5 returns 2.
Інкремент (++) Унарний оператор. Додає до свого операнда одиницю. Бувши вжитим як префіксний оператор (++x), повертає значення свого операнда після додавання одиниці, а якщо як постфіксний (x++), то до додавання одиниці. Якщо x має значення 3, то ++x присвоює x значення 4 і повертає 4, натомість x++ повертає 3, і лише після цього присвоює x значення 4.
Декремент (--) Унарний оператор. Віднімає від свого операнда одиницю. Повернене значення – аналогічне до поверненого значення оператора інкременту. Якщо x має значення 3, то --x присвоює x значення 2 і повертає 2, натомість x-- повертає 3, і лише після цього присвоює x значення 2.
Унарна протилежність (-) Унарний оператор. Повертає протилежність до свого операнда. Якщо x має значення 3, то -x повертає -3.
Унарний плюс (+) Унарний оператор. Намагається перетворити свій операнд на число, якщо він ним не є.

+"3" повертає 3.

+true повертає 1.

Піднесення до степеня (**) Обчислює піднесення числа base до степеня exponent, тобто base^exponent 2 ** 3 повертає 8.
10 ** -1 повертає 0.1.

Бітові оператори

Бітові оператори розглядають свої операнди як набори з 32 бітів (нулів та одиниць), а не як десяткові, шістнадцяткові або вісімкові числа. Наприклад, десяткове число дев'ять має двійкове представлення 1001. Бітові оператори виконують свої операції над таким двійковим представленням, але повертають звичайні числові значення JavaScript.

Наступна таблиця містить підсумок бітових операторів JavaScript.

Оператор Застосування Опис
Бітова кон'юнкція a & b Повертає одиницю в кожній бітовій позиції, в якій відповідні біти обох операндів – одиниці.
Бітова диз'юнкція a | b Повертає нуль в кожній бітовій позиції, в якій відповідні біти обох операндів – нулі.
Бітова виключна диз'юнкція a ^ b Повертає нуль у кожній бітовій позиції, в якій відповідні біти – однакові (Повертає одиницю в кожній бітовій позиції, в якій відповідні біти – різні).]
Бітове заперечення ~ a Міняє біти свого операнда на протилежні.
Зсув уліво a << b Зсуває a у двійковому представленні на b бітів уліво, вставляючи нулі справа.
Зсув управо зі збереженням знаку a >> b Зсуває a у двійковому представленні на b бітів управо, відкидаючи висунуті біти.
Зсув управо з додаванням нулів a >>> b Зсуває a у двійковому представленні на b бітів управо, відкидаючи висунуті біти, і доставляючи зліва нулі.

Бітові логічні оператори

Концептуально бітові логічні оператори працюють так:

  • Операнди перетворюються на тридцятидвобітні цілі числа, виражені послідовностями бітів (нулів та одиниць). Найважливіші біти чисел, котрі мають більш ніж 32 біти, відкидаються. Наприклад, наступне ціле число, котре має понад 32 біти, перетворюється на 32-бітове ціле:

    До:    1110 0110 1111 1010 0000 0000 0000 0110 0000 0000 0001
    Після:                1010 0000 0000 0000 0110 0000 0000 0001
    
  • Кожний біт першого операнда зіставляється з відповідним бітом другого операнда: перший біт до першого біта, другий біт до другого біта – і так далі.

  • Оператор застосовується до кожної пари бітів, а результат збирається з бітових результатів.

Наприклад, двійкове представлення дев'яти – 1001, а двійкове представлення п'ятнадцяти – 1111. Таким чином, коли до цих значень застосувати бітові оператори, то результати будуть такі:

Вираз Результат Двійковий опис
15 & 9 9 1111 & 1001 = 1001
15 | 9 15 1111 | 1001 = 1111
15 ^ 9 6 1111 ^ 1001 = 0110
~15 -16 ~ 0000 0000 … 0000 1111 = 1111 1111 … 1111 0000
~9 -10 ~ 0000 0000 … 0000 1001 = 1111 1111 … 1111 0110

Зверніть увагу на те, що всі 32 біти – змінюються на протилежні за допомогою оператора бітового заперечення, і що значення з найважливішим (крайнім зліва) бітом 1 представляють від'ємні числа (доповнювальне представлення). ~x обчислюється в таке ж значення, що й -x - 1.

Оператори бітового зсуву

Оператори бітового зсуву приймають два операнди: перший – число до зсуву, а другий – це число бітових позицій, на яке буде зсунутий перший операнд. Напрям операції зсуву визначається застосованим оператором.

Оператори зсуву перетворюють свої операнди на тридцятидвобітні цілі числа й повертають результат або типуNumber, або BigInt, а саме: якщо тип лівого операнда – BigInt, то вони повертають BigInt, інакше – Number.

Оператори зсуву перелічені в наступній таблиці.

Оператори бітового зсуву
Оператори Опис Приклад
Зсув уліво
(<<)
Цей оператор зсуває перший операнд на задану кількість бітів уліво. Надлишкові біти зліва – відкидаються. Справа – доставляються нулі. 9<<2 видає 36, тому що 1001, зсунуте на 2 біти уліво, стає 100100, тобто 36.
Зсув управо зі збереженням знаку (>>) Цей оператор зсуває перший операнд на задану кількість бітів управо. Надлишкові біти справа – відкидаються. Зліва доставляються копії крайнього лівого біта. 9>>2 видає 2, тому що 1001, зсунуте на 2 бітів управо, стає 10, тобто 2. Аналогічно, -9>>2 видає -3, тому що знак зберігається.
Зсув управо з додаванням нулів (>>>) Цей оператор зсуває перший операнд на задану кількість бітів управо. Надлишкові біти справа – відкидаються. Зліва – доставляються нульові біти. 19>>>2 видає 4, адже 10011, зсунуте на 2 біти управо, стає 100, тобто 4. У випадку невід'ємних чисел зсув управо із додаванням нулів і зсув управо зі збереженням знаку видають однакові результати.

Логічні оператори

Логічні оператори здебільшого застосовуються на булевих (логічних) значеннях; коли це так, то вони повертають булеві значення. Проте оператори && і || фактично повертають значення одного з переданих операндів, тож коли ці оператори застосовуються до небулевих значень, то ці оператори можуть повернути небулеві значення. Логічні оператори описані в наступній таблиці.

Логічні оператори
Оператор Застосування Опис
Логічна кон'юнкція (&&) expr1 && expr2 Повертає expr1, якщо це значення може бути перетворено на false, інакше – повертає expr2. Таким чином, бувши застосованим до булевих значень, оператор && повертає true, якщо обидва операнди – true, інакше – повертає false.
Логічна диз'юнкція (||) expr1 || expr2 Повертає expr1, якщо це значення може бути перетворено на true, інакше повертає expr2. Таким чином, бувши застосованим до булевих значень, оператор || повертає true, якщо будь-який з операндів – true, якщо ж обидва вони – false, то повертає false.
Логічне заперечення (!) !expr Повертає false, якщо єдиний операнд оператора може бути перетворений на true, інакше – повертає true.

Прикладами виразів, котрі можуть бути перетворені на false, є ті вирази, котрі обчислюються в null, 0, NaN, порожній рядок ("") та undefined.

Наступний код демонструє приклади застосування оператора && (логічної кон'юнкції).

const a1 = true && true; // t && t повертає true
const a2 = true && false; // t && f повертає false
const a3 = false && true; // f && t повертає false
const a4 = false && 3 === 4; // f && f повертає false
const a5 = "Кіт" && "Пес"; // t && t повертає Пес
const a6 = false && "Кіт"; // f && t повертає false
const a7 = "Кіт" && false; // t && f повертає false

Наступний код демонструє приклади застосування оператора || (логічної диз'юнкції).

const o1 = true || true; // t || t повертає true
const o2 = false || true; // f || t повертає true
const o3 = true || false; // t || f повертає true
const o4 = false || 3 === 4; // f || f повертає false
const o5 = "Кіт" || "Пес"; // t || t повертає Кіт
const o6 = false || "Кіт"; // f || t повертає Кіт
const o7 = "Кіт" || false; // t || f повертає Кіт

Наступний код демонструє приклади застосування оператора ! (логічного заперечення).

const n1 = !true; // !t повертає false
const n2 = !false; // !f повертає true
const n3 = !"Кіт"; // !t повертає false

Закорочення обчислення

Оскільки логічні вирази обчислюються зліва направо, то вони перевіряються на змогу "закоротити" обчислення, згідно з наступними правилами:

  • false && щось – із закороченням обчислюється в false.
  • true || щось – із закороченням обчислюється в true.

Правила логіки гарантують, що такі обчислення завжди є коректними. Зверніть увагу на те, що частина щось виразів вище – не обчислюється, тож жодні побічні ефекти цих частин – не подіють.

Зверніть увагу на те, що в сучасному коді можна застосувати оператор null-злиття (??), котрий працює подібно до ||, але повертає другий вираз лише тоді, коли перший вираз є "null-подібним", тобто null або undefined. Таким чином, це кращий варіант для надання усталених значень у тих випадках, коли '' і 0 є дійсними значеннями першого виразу.

Оператори BigInt

Більшість операторів, котрі можуть бути застосовані до двох чисел, може бути застосована також до значень BigInt.

// Додавання BigInt
const a = 1n + 2n; // 3n
// Ділення BigInts округлюється в бік нуля
const b = 1n / 2n; // 0n
// Бітові операції над BigInts не обрізають число з жодного боку
const c = 40000000000000000n >> 2n; // 10000000000000000n

Винятком є беззнаковий зсув управо (>>>), котрий не визначений для значень BigInt. Це пов'язано з тим, що BigInt не має фіксованої ширини, тож технічно цей тип не має "крайнього зліва біта".

const d = 8n >>> 2n; // TypeError: BigInts have no unsigned right shift, use >> instead

Значення BigInt і числа не є взаємозамінними – їх не можна змішувати при обчисленнях.

const a = 1n + 2; // TypeError: Cannot mix BigInt and other types

Це пов'язано з тим, що BigInt не є ані підмножиною, ані надмножиною чисел. Значення BigInt мають вищу точність, ніж звичайні числа, при представленні великих цілих, але не можуть представляти дроби, тож неявне перетворення в обидва боки може призвести до втрати точності. Слід використовувати явне перетворення для позначення того, чи повинна операція відбуватися над звичайними числами, чи над BigInt.

const a = Number(1n) + 2; // 3
const b = 1n + BigInt(2); // 3n

Можна порівнювати BigInt з числами.

const a = 1n > 2; // false
const b = 3 > 2n; // true

Рядкові оператори

На додачу до операторів порівняння, котрі можна застосовувати до рядкових значень, оператор зчеплення (+) зчіплює два рядкові значення докупи, повертаючи новий рядок, котрий є сполученням двох рядків – операндів.

Наприклад,

console.log("my " + "string"); // консоль виводить рядок "my string".

Оператор присвоєння зі скороченням += також може використовуватись для зчеплення рядків.

Наприклад,

let mystring = "alpha";
mystring += "bet"; // обчислюється в "alphabet" й присвоює це значення mystring.

Умовний (тернарний) оператор

Умовний оператор – це єдиний оператор JavaScript, котрий приймає три операнди. Він може приймати одне з двох значень, залежно від умови. Запис – наступний:

condition ? val1 : val2

Якщо condition істинна, то оператор має значення val1. Інакше – він має значення val2. Умовний оператор можна використовувати всюди, де можна було б використати стандартний оператор.

Наприклад,

const status = age >= 18 ? "adult" : "minor";

Ця інструкція присвоює значення "adult" змінній status, якщо age має значення вісімнадцяти або більше. Інакше, змінній status присвоюється значення "minor".

Оператор коми

Оператор коми (,) обчислює обидва свої операнди й повертає значення останнього з них. Цей оператор перш за все використовується в циклі for, аби мати змогу оновлювати декілька змінних при кожній ітерації циклу. Вживання оператора коми вважається недоброю практикою, коли це не є необхідністю. Нерідко замість цього можна й варто використати дві окремі інструкції.

Наприклад, якщо a – це двовимірний масив з 10 елементами в кожному підмасиві, то наступний код використовує оператор коми, аби оновити дві змінні за раз. Цей код виводить значення діагональних елементів масиву:

const x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
const a = [x, x, x, x, x];

for (let i = 0, j = 9; i <= j; i++, j--) {
  //                              ^
  console.log(`a[${i}][${j}]= ${a[i][j]}`);
}

Унарні оператори

Унарна операція – це операція лише з одним операндом.

delete

Оператор delete видаляє властивість об'єкта. Запис – наступний:

delete object.property;
delete object[propertyKey];
delete objectName[index];

де object – це назва об'єкта, property – його наявна властивість, а propertyKey – рядок або символ, що вказує на наявну властивість.

Коли оператор delete має успіх, то прибирає з об'єкта властивість. Спроба звернутись до неї після цього видасть undefined. Оператор delete повертає true, якщо операція можлива, і false, якщо вона неможлива.

delete Math.PI; // повертає false (не можна видаляти неналаштовні властивості)

const myObj = { h: 4 };
delete myObj.h; // повертає true (визначені користувачем властивості видаляти можна)

Видалення елементів масиву

Оскільки масиви є лишень об'єктами, технічно можливо застосувати до них оператор delete. Проте це вважається недоброю практикою, так робити не варто. Коли видаляється властивість масиву, то це не впливає на його довжину, а решта елементів не отримує нових індексів. Для прибирання елемента з масиву краще просто записати замість нього значення undefined. Задля фактичного змінювання масиву слід використовувати різні методи масиву, як то splice.

typeof

Оператор typeof повертає рядок, котрий вказує на тип необчисленого операнда. operand – це рядок, змінна, ключове слово або об'єкт, тип якого буде повернений. Дужки – необов'язкові.

Припустімо, що оголошені наступні змінні:

const myFun = new Function("5 + 2");
const shape = "round";
const size = 1;
const foo = ["Apple", "Mango", "Orange"];
const today = new Date();

Оператор typeof поверне для них наступні результати:

typeof myFun; // повертає "function"
typeof shape; // повертає "string"
typeof size; // повертає "number"
typeof foo; // повертає "object"
typeof today; // повертає "object"
typeof doesntExist; // повертає "undefined"

Для ключових слів true і null оператор typeof повертає наступні результати:

typeof true; // повертає "boolean"
typeof null; // повертає "object"

Для числа або рядка:

typeof 62; // повертає "number"
typeof "Hello world"; // повертає "string"

Для значень властивостей оператор typeof повертає тип значення, котре така властивість містить:

typeof document.lastModified; // повертає "string"
typeof window.length; // повертає "number"
typeof Math.LN2; // повертає "number"

Для методів і функцій оператор typeof повертає таке:

typeof blur; // повертає "function"
typeof eval; // повертає "function"
typeof parseInt; // повертає "function"
typeof shape.split; // повертає "function"

Для наперед визначених об'єктів:

typeof Date; // повертає "function"
typeof Function; // повертає "function"
typeof Math; // повертає "object"
typeof Option; // повертає "function"
typeof String; // повертає "function"

void

Оператор void позначає вираз як такий, що повинен бути обчислений без повернення значення. expression – це вираз JavaScript для обчислення. Дужки навколо виразу – необов'язкові, але краще їх використовувати, аби уникати проблем з пріоритетом.

Оператори відношення

Оператори відношення порівнюють свої операнди й повертають булеве значення на основі істинності порівняння.

in

Оператор in повертає true, якщо дана властивість існує в даному об'єкті. Запис – наступний:

propNameOrNumber in objectName

де propNameOrNumber – це рядковий, числовий або символьний вираз, що представляє назву властивості або індекс масиву, а objectName – це назва об'єкта.

Наступні приклади демонструють кілька варіантів використання оператора in.

// Масиви
const trees = ["redwood", "bay", "cedar", "oak", "maple"];
0 in trees; // повертає true
3 in trees; // повертає true
6 in trees; // повертає false
"bay" in trees; // повертає false
// (необхідно задати число-індекс, а не значення за цим індексом)
"length" in trees; // повертає true (length – це властивість масива)

// вбудовані об'єкти
"PI" in Math; // повертає true
const myString = new String("coral");
"length" in myString; // повертає true

// Власні об'єкти
const mycar = { make: "Honda", model: "Accord", year: 1998 };
"make" in mycar; // повертає true
"model" in mycar; // повертає true

instanceof

Оператор instanceof повертає true, якщо даний об'єкт належить до даного об'єктного типу. Запис – наступний:

objectName instanceof objectType

де objectName – це назва об'єкта до порівняння з objectType, а objectType – об'єктний тип, наприклад, Date або Array.

Використовувати instanceof слід тоді, коли необхідно перевірити тип об'єкта під час виконання. Наприклад, при перехопленні винятків, може бути потреба обробляти по-різному викинуті винятки, залежно від їх типу.

Наприклад, наступний код використовує instanceof для з'ясування того, чи є theDay об'єктом Date. Оскільки theDay є об'єктом Date, то інструкції всередині інструкції if – виконуються.

const theDay = new Date(1995, 12, 17);
if (theDay instanceof Date) {
  // інструкції до виконання
}

Базові вирази

Усі оператори, зрештою, працюють з одним чи багатьма базовими виразами. Серед цих базових виразів – ідентифікатори й літерали, однак є й кілька інших різновидів. Ці різновиди стисло вводяться нижче, а їхня семантика детально описана у відповідних розділах довідки.

this

Ключове слово this слід використовувати для звертання до поточного об'єкта. Загалом, this вказує на об'єкт, з якого викликається метод. this слід вживати із записом крапки або квадратних дужок:

this["propertyName"];
this.propertyName;

Припустімо, що функція під назвою validate валідує властивість value об'єкта, отримавши об'єкт та межі допустимого діапазону для value:

function validate(obj, lowval, hival) {
  if (obj.value < lowval || obj.value > hival) {
    console.log("Недійсне значення!");
  }
}

validate можна викликати в кожному обробнику подій onChange елемента форми, використовуючи this для передачі цього елемента, як це показано в наступному прикладі:

<p>Введіть число між 18 і 99:</p>
<input type="text" name="age" size="3" onChange="validate(this, 18, 99);" />

Оператор групування

Оператор групування ( ) контролює пріоритет обчислення у виразах. Наприклад, можна відкинути першість множення й ділення перед додаванням і відніманням - і обчислити спершу додавання.

const a = 1;
const b = 2;
const c = 3;

// усталений пріоритет
a + b * c     // 7
// усталено обчислюється так
a + (b * c)   // 7

// тепер нав'язуємо пріоритет
// додавання перед множенням
(a + b) * c   // 9

// що рівносильно
a * c + b * c // 9

new

Оператор new можна використовувати для створення примірника власного об'єктного типу або одного із вбудованих об'єктних типів. Робиться це так:

const objectName = new ObjectType(param1, param2, /* …, */ paramN);

super

Ключове слово super використовується для виклику функцій на батьківському об'єкті. Корисно, наприклад, при використанні класів – викликати батьківський конструктор.

super(args); // викликається батьківський конструктор.
super.functionOnParent(args);