Skip to content

Найпопулярніші запитання та відповіді на співбесіді з JavaScript

License

Notifications You must be signed in to change notification settings

FrontendLovers/javascript-interview-questions

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

12 Commits
 
 
 
 
 
 
 
 

Repository files navigation

JavaScript

Найпопулярніші запитання та відповіді на співбесіді з JavaScript

1. Що таке JavaScript?
  • JavaScript — це динамічна, прототипно-орієнтована мова програмування, яка використовується для створення інтерактивного контенту на вебсторінках. Вона підтримує подієве програмування, асинхронність і працює в браузері, а також на сервері через Node.js.
2. Які ключові слова використовуються для оголошення змінних у JavaScript?
  • У JavaScript змінні можна оголошувати за допомогою трьох ключових слів:
  1. var
  • Старий спосіб оголошення змінних.

  • Область видимості: функціональна (в межах функції, а не блоку).

  • Підтримує підняття (hoisting): змінну можна використовувати до оголошення, але значення буде undefined.

  • Не рекомендується через можливість помилок.

    var x = 10;
  1. let
  • Використовується для змінних, які можуть змінювати значення.

  • Область видимості: блочна (в межах {}).

  • Не дозволяє повторного оголошення в межах однієї області.

  • Не піддається підняттю з доступом до значення.

    let y = 20;
    y = 30; // Можна змінити значення
  1. const
  • Використовується для змінних, значення яких не змінюється.

  • Область видимості: блочна.

  • Потрібно обов’язково ініціалізувати при оголошенні.

  • Якщо змінна є об’єктом або масивом, значення властивостей можна змінювати, але саму змінну перевизначити не можна.

    const z = 40;
    // z = 50; // Помилка
  • Рекомендації:

    • Використовувати const для змінних, які не змінюються.
    • Використовувати let для змінних, які змінюють значення.
    • var уникати, якщо це не потрібно для специфічної підтримки старих браузерів.
3. Перерахуйте типи даних у JavaScript.
  1. Примітивні:
  • string
  • number
  • boolean
  • null
  • undefined
  • bigint
  • symbol
  1. Складні:
  • object (включаючи масиви, функції, дати тощо).
4. У чому різниця між функціональним (functional) і подієвим (event-driven) програмуванням у JavaScript?
  • Функціональне програмування:

    • Базується на чистих функціях, які не мають побічних ефектів.
    • Дані не змінюються, використовується іммутабельність.
    • Код пишеться у вигляді композиції функцій (map, reduce, filter).
    • Наприклад: обробка даних у масиві через функції вищого порядку.
  • Подієве програмування:

    • Реакція на події (click, hover, async responses).
    • Використовує слухачі (event listeners) та обробники подій (callbacks).
    • Побудоване на взаємодії з подіями в середовищі (браузері чи Node.js).
    • Наприклад: виклик функції при кліку на кнопку.
5. У якому році відбувся перший реліз JavaScript, і в якому браузері він був вперше використаний?
  • Перший реліз JavaScript відбувся в 1995 році. Він був вперше реалізований у браузері Netscape Navigator.
6. Чим відрізняється масив та обʼєкт? У яких випадках що використовуєте?
  • Масив:

    • Використовується для зберігання впорядкованих елементів.
    • Індексовані значення (0, 1, 2, …).
    • Підходить для роботи з колекціями даних, де порядок важливий або коли потрібно виконувати операції типу сортування.
  • Обʼєкт:

    • Використовується для зберігання пар "ключ-значення".
    • Доступ до значень через ключі (не індекси).
    • Підходить для зберігання даних з різними властивостями або для створення складних структур.
  • Використання:

  1. Масив: коли порядок елементів важливий або ви працюєте з колекцією однотипних елементів (наприклад, список користувачів).
  2. Обʼєкт: коли потрібно зберігати дані з різними властивостями або асоціативні пари (наприклад, профіль користувача з різними атрибутами).
7. Events в JavaScript. Розкажіть про event propagation, bubbling, delegation, preventing тощо.
  • Event Propagation — це процес, при якому подія, що сталася на елементі, "поширюється" через DOM дерево. Є два основні етапи:
  1. Bubbling (Спливання): Подія спочатку викликається на найбільш вкладеному елементі, потім вона спливає до батьківських елементів (від внутрішнього до зовнішнього). Наприклад, якщо клікнути на кнопку всередині контейнера, подія спочатку буде оброблятися кнопкою, потім контейнером, і так далі, поки не досягне кореневого елемента (document).

  2. Capturing (Ловлення): Подія спочатку обробляється на найвищому рівні DOM дерева (наприклад, document), а потім спускається вниз до цільового елемента.

  • Event Delegation — це техніка обробки подій, коли ви додаєте один обробник подій на батьківський елемент, а не на кожен окремий дочірній елемент. Це дозволяє зменшити кількість обробників і є ефективним способом обробки подій на динамічно створених елементах.

  • Preventing Default Behavior (Запобігання стандартній поведінці):

    • Метод event.preventDefault() дозволяє зупинити стандартну поведінку події. Наприклад, можна скасувати перезавантаження сторінки при натисканні на посилання або скасувати відправку форми.
  • stopPropagation() vs. stopImmediatePropagation():

    • stopPropagation(): Зупиняє подальше поширення події по DOM, але не скасовує інші обробники подій на поточному елементі.
    • stopImmediatePropagation(): Зупиняє подальше поширення події і скасовує інші обробники подій, що могли бути зареєстровані на тому самому елементі.
8. Чи можливо перевизначити const?
  • Ні, значення, оголошене через const, не можна змінити. Це означає, що ви не можете переназначити змінну, оголошену з const, на нове значення. Однак, якщо const використовується для оголошення обʼєкта або масиву, ви все ще можете змінювати його вміст (наприклад, додавати властивості до обʼєкта або елементи до масиву). Тобто, const гарантує, що сама змінна не може бути переназначена, але не захищає від змін всередині складних типів даних (масивів, обʼєктів).
9. Чи відомі вам принципи DRY, KISS, YAGNI, SOLID?
  • Так, ці принципи широко використовуються в програмуванні для забезпечення чистого, підтримуваного і ефективного коду.
  1. DRY (Don't Repeat Yourself) — уникайте дублювання коду. Якщо одна й та сама логіка зустрічається в кількох місцях, варто створити спільну функцію або метод, щоб зробити код більш зручним для підтримки.

  2. KISS (Keep It Simple, Stupid) — підтримуйте код простим і зрозумілим. Уникайте надмірної складності і зайвих абстракцій. Простота покращує підтримуваність і знижує ймовірність помилок.

  3. YAGNI (You Aren't Gonna Need It) — не додавайте функціональність, яку наразі не потрібно. Створювати код тільки для майбутніх можливостей може призвести до зайвих витрат часу і складності.

  4. SOLID — набір принципів для об'єктно-орієнтованого програмування, що допомагають створювати гнучкий, зрозумілий і підтримуваний код:

  • S (Single Responsibility Principle) — кожен клас чи функція має виконувати одну задачу.
  • O (Open/Closed Principle) — код має бути відкритим для розширення, але закритим для модифікації.
  • L (Liskov Substitution Principle) — обʼєкти підкласів повинні заміняти обʼєкти батьківських класів без порушення роботи програми.
  • I (Interface Segregation Principle) — не змушуйте класи реалізовувати інтерфейси, які вони не використовують.
  • D (Dependency Inversion Principle) — залежності повинні бути від абстракцій, а не від конкретних класів.
10. У чому відмінності LocalStorage від SessionStorage?
  • LocalStorage:

    • Зберігає дані без обмежень по часу, дані зберігаються навіть після закриття браузера або вкладки.
    • Доступні для всіх вкладок і вікон того ж самого домену.
    • Обмеження на обсяг — зазвичай 5-10 МБ на домен.
    • Дані зберігаються, поки вони не будуть явно видалені.
  • SessionStorage:

    • Дані зберігаються тільки в межах однієї сесії (до закриття вкладки або вікна браузера).
    • Доступні тільки в тій самій вкладці або вікні, в якій були збережені.
    • Обсяг схожий на LocalStorage (5-10 МБ).
    • Дані видаляються автоматично при закритті вкладки або браузера.
  • Основні відмінності:

    • Тривалість зберігання: LocalStorage — дані зберігаються постійно, SessionStorage — тільки на час сесії.
    • Доступність: LocalStorage доступний для всіх вкладок, SessionStorage — тільки для поточної вкладки.
11. Що таке замикання (closure) в JavaScript і як воно працює?
  • Замикання (closure) — це функція, яка "запам'ятовує" оточення, в якому була створена. Це дозволяє функції доступ до змінних, навіть після того, як зовнішня функція, в якій вона була оголошена, завершила своє виконання.

  • Як це працює:

    • Оточення: Кожна функція в JavaScript має доступ до змінних, які знаходяться в її власному оточенні (локальні змінні), а також до змінних, які були доступні в оточенні, де функція була створена.
    • Замикання: Коли функція всередині іншої функції повертається або передається, вона все ще має доступ до змінних оточення, навіть якщо зовнішня функція вже завершила виконання.
  • Приклад:

    function outer() {
      let counter = 0; // локальна змінна зовнішньої функції
    
      return function inner() {
        // внутрішня функція
        counter++; // доступ до змінної outer()
        console.log(counter);
      };
    }
    
    const increment = outer(); // викликаємо outer, що повертає функцію inner
    increment(); // виведе 1
    increment(); // виведе 2
12. Що таке Кукі (cookies) і як вони працюють в JavaScript?
  • Кукі (cookies) — це невеликі фрагменти даних, які вебсайт зберігає в браузері користувача. Вони використовуються для зберігання інформації, яка може бути використана для ідентифікації користувача, збереження налаштувань, відслідковування сесій тощо.

  • Як працюють кукі в JavaScript:

  1. Зчитування кукі: Веб-браузер автоматично додає всі кукі для поточного домену до заголовка запиту, і JavaScript може отримати їх через document.cookie.

    const cookies = document.cookie;
    console.log(cookies); // виведе всі кукі у вигляді рядка
  2. Запис кукі: Кукі встановлюються за допомогою властивості document.cookie. Формат для встановлення кукі виглядає так:

    document.cookie =
      "name=value; expires=Thu, 31 Dec 2025 23:59:59 UTC; path=/";
    • У цьому прикладі:

      • "name=value" — це ключ-значення кукі.
      • expires — вказує дату, коли кукі стане неактивним. Якщо не вказано, кукі буде тимчасовим і видалиться після закриття браузера.
      • path — визначає, до якого шляху на сайті доступна кукі.
  3. Видалення кукі: Щоб видалити кукі, потрібно встановити її термін придатності в минуле:

    document.cookie = "name=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";
  • Особливості:

    • Термін дії: Кукі можуть бути тимчасовими або мати встановлений термін дії.
    • Обмеження на розмір: Кожна кукі може зберігати до 4 КБ даних, і браузер зберігає до 20 кукі на домен.
    • Обмеження на доступність: Кукі можуть бути доступні лише на тому домені і підкаталозі, де вони були встановлені.
    • Безпека: Кукі можуть бути позначені як Secure (щоб передавались лише через HTTPS) і HttpOnly (щоб вони не були доступні через JavaScript).
  • Використання кукі:

    • Ідентифікація користувача (наприклад, для збереження сесій).
    • Збереження налаштувань користувача (темна/світла тема, мова сайту).
    • Відслідковування статистики (аналітика).
    • Кукі є важливим інструментом для взаємодії між клієнтом і сервером, але їх потрібно використовувати обережно через питання конфіденційності та безпеки.
13. Що таке область видимості змінної?
  • Область видимості змінної — це частина коду, в межах якої до змінної можна отримати доступ. У JavaScript існують три основні типи області видимості:
  1. Глобальна область видимості (Global Scope):
  • Змінна доступна у всьому коді.

  • Змінні, оголошені поза будь-якими функціями або блоками, автоматично стають глобальними.

  • Глобальні змінні створюються з використанням ключових слів var, let, const, або без них (хоча останнє — погана практика).

    var globalVar = "I am global"; // доступна у всьому коді
    
    function test() {
      console.log(globalVar); // доступ до глобальної змінної
    }
    test();
  1. Функціональна область видимості (Function Scope):
  • Змінні, оголошені всередині функції з використанням var, доступні лише в межах цієї функції.

  • Ця область видимості застосовується лише до var. Змінні let і const підкоряються блочній області видимості.

    function test() {
      var localVar = "I am local";
      console.log(localVar); // доступна всередині функції
    }
    test();
    console.log(localVar); // помилка: localVar не визначена
  1. Блочна область видимості (Block Scope):
  • Змінні, оголошені з використанням let або const, доступні тільки всередині блоку {}.

  • Не застосовується до змінних, оголошених через var.

    {
      let blockVar = "I am block scoped";
      const blockConst = "I am also block scoped";
      console.log(blockVar); // доступна
    }
    console.log(blockVar); // помилка: blockVar не визначена
  • Вкладені області видимості:

    • Внутрішня область може отримати доступ до змінних з зовнішньої області, але не навпаки.
    function outer() {
      let outerVar = "outer";
      function inner() {
        console.log(outerVar); // доступ до змінної зовнішньої функції
      }
      inner();
    }
    outer();
  • Hoisting (Підняття):

    • У JavaScript змінні, оголошені через var, "піднімаються" на початок своєї області видимості, але без ініціалізації.

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

    console.log(a); // undefined
    var a = 10;
    
    console.log(b); // помилка
    let b = 20;
14. Що таке анонімна функція?
  • Анонімна функція — це функція, яка не має імені. Вона часто використовується там, де функцію потрібно створити швидко і немає необхідності використовувати її повторно.

  • Приклади анонімних функцій у JavaScript:

  1. Функція як аргумент: Анонімні функції часто передаються як аргументи до інших функцій (наприклад, у методах map, filter, forEach).

    const numbers = [1, 2, 3];
    const doubled = numbers.map(function (num) {
      return num * 2;
    });
    console.log(doubled); // [2, 4, 6]
  2. Функціональний вираз: Анонімна функція може бути присвоєна змінній.

    const greet = function () {
      console.log("Hello");
    };
    greet(); // Hello
  3. Самовиконувана функція (IIFE): Анонімна функція може бути негайно виконана.

    (function () {
      console.log("I am an IIFE");
    })();
  4. У стрілкових функціях: Стрілкові функції — це синтаксично скорочений варіант анонімних функцій.

    const add = (a, b) => a + b;
    console.log(add(2, 3)); // 5
  • Переваги анонімних функцій:

    • Короткий синтаксис: Особливо у випадку однорядкових функцій.
    • Локальність: Використовуються лише там, де потрібні, що сприяє чистоті коду.
  • Недоліки:

    • Немає імені: Ускладнюється налагодження коду, оскільки у стеку викликів такі функції позначаються як <anonymous>.
    • Відсутність повторного використання: Не можна викликати повторно без збереження в змінну або передачі куди-небудь.
15. Що таке стрілкова функція і як вона відрізняється від звичайної функції?
  • Стрілкова функція (arrow function) — це скорочений синтаксис для оголошення функцій у JavaScript, введений в ES6. Вона має компактну форму і поводиться інакше, ніж звичайна функція, особливо щодо контексту this.

  • Синтаксис:

    const functionName = (param1, param2) => {
      // тіло функції
      return param1 + param2;
    };
  • Приклад однорядкової функції:

    const add = (a, b) => a + b; // автоматично повертає результат
    console.log(add(2, 3)); // 5
  • Основні відмінності:

  1. Контекст this:

    • У стрілкових функцій немає власного this. Вони успадковують this із зовнішнього оточення.
    • У звичайних функцій this залежить від способу виклику (динамічно прив'язується).
    const obj = {
      value: 10,
      regularFunction: function () {
        console.log(this.value); // 10
      },
      arrowFunction: () => {
        console.log(this.value); // undefined (успадковує this із глобального контексту)
      },
    };
    
    obj.regularFunction();
    obj.arrowFunction();
  2. Конструктор:

    • Стрілкові функції не можуть використовуватися як конструктори.
    • Виклик new зі стрілковою функцією викликає помилку.
    const Arrow = () => {};
    const Regular = function () {};
    
    new Arrow(); // Помилка
    new Regular(); // Працює
  3. Синтаксис:

    • Стрілкова функція більш лаконічна, особливо для однорядкових операцій.
    • Звичайна функція може мати більш розгорнутий вигляд, але є універсальною.
    // Звичайна функція
    function multiply(a, b) {
      return a * b;
    }
    
    // Стрілкова функція
    const multiplyArrow = (a, b) => a * b;
  4. arguments:

    • У стрілкових функцій немає псевдомасиву arguments. Щоб отримати аргументи, слід використовувати оператор rest (...).
    • У звичайних функцій є доступ до arguments.
    const regularFunc = function () {
      console.log(arguments); // Псевдомасив
    };
    
    const arrowFunc = (...args) => {
      console.log(args); // Справжній масив
    };
    
    regularFunc(1, 2, 3);
    arrowFunc(1, 2, 3);
  5. Ключове слово super:

    • Стрілкові функції успадковують super із зовнішнього контексту.
    • У звичайних функцій super визначається залежно від їх виклику.
  • Коли використовувати:

    • Стрілкові функції добре підходять для коротких виразів, обробників подій, методів масивів (map, filter, reduce), а також там, де важливе збереження контексту this.
    • Звичайні функції варто використовувати для більш складних сценаріїв, що потребують власного this, arguments або можливості виклику через new.
16. Які методи перебору масивів ви знаєте?
  • Основні методи перебору масивів у JavaScript:
  1. forEach

    • Викликає передану функцію для кожного елемента масиву.
    • Нічого не повертає (завжди undefined).
    const arr = [1, 2, 3];
    arr.forEach((num) => console.log(num));
    // Виведе: 1, 2, 3
  2. map

    • Створює новий масив, застосовуючи передану функцію до кожного елемента.
    • Не змінює вихідний масив.
    const arr = [1, 2, 3];
    const doubled = arr.map((num) => num * 2);
    console.log(doubled); // [2, 4, 6]
  3. filter

    • Створює новий масив із елементів, що відповідають умовам функції.
    const arr = [1, 2, 3, 4];
    const even = arr.filter((num) => num % 2 === 0);
    console.log(even); // [2, 4]
  4. reduce

    • Агрегує масив в одне значення, використовуючи функцію та початкове значення.
    const arr = [1, 2, 3];
    const sum = arr.reduce((acc, num) => acc + num, 0);
    console.log(sum); // 6
  5. some

    • Повертає true, якщо хоч один елемент відповідає умові.
    const arr = [1, 2, 3];
    console.log(arr.some((num) => num > 2)); // true
  6. every

    • Повертає true, якщо всі елементи відповідають умові.
    const arr = [2, 4, 6];
    console.log(arr.every((num) => num % 2 === 0)); // true
  7. find

    • Повертає перший елемент, що відповідає умові, або undefined.
    const arr = [1, 2, 3];
    console.log(arr.find((num) => num > 1)); // 2
  8. findIndex

    • Повертає індекс першого елемента, що відповідає умові, або -1.
    const arr = [1, 2, 3];
    console.log(arr.findIndex((num) => num > 1)); // 1
  9. flatMap

    • Поєднує функціональність map і flat. Повертає плоский масив.
    const arr = [1, 2, 3];
    console.log(arr.flatMap((num) => [num, num * 2])); // [1, 2, 2, 4, 3, 6]
  10. keys, values, entries

    • keys: ітератор ключів (індексів).
    • values: ітератор значень.
    • entries: ітератор пар [індекс, значення].
    const arr = ["a", "b", "c"];
    for (let key of arr.keys()) console.log(key); // 0, 1, 2
    for (let value of arr.values()) console.log(value); // 'a', 'b', 'c'
    for (let [index, value] of arr.entries()) console.log(index, value); // 0 'a', 1 'b', 2 'c'
  11. for...of

    • Простий синтаксис для ітерації масивів.
    const arr = [1, 2, 3];
    for (const num of arr) console.log(num);
    // Виведе: 1, 2, 3
  12. sort

    • Сортує масив на місці.
    const arr = [3, 1, 2];
    arr.sort((a, b) => a - b);
    console.log(arr); // [1, 2, 3]
  13. reverse

    • Перевертає порядок елементів у масиві.
    const arr = [1, 2, 3];
    arr.reverse();
    console.log(arr); // [3, 2, 1]
  14. slice

    • Повертає копію частини масиву.
    const arr = [1, 2, 3];
    const subArr = arr.slice(1);
    console.log(subArr); // [2, 3]
  15. splice

    • Додає, видаляє або замінює елементи в масиві.
    const arr = [1, 2, 3];
    arr.splice(1, 1, 4); // Видаляє 1 елемент із позиції 1, додає 4
    console.log(arr); // [1, 4, 3]
  • Вибір методу залежить від задачі:
    • Для фільтрації: filter.
    • Для перетворення: map.
    • Для пошуку: find / findIndex.
    • Для ітерації: forEach / for...of.
17. Що таке JSON і як працювати з ним у JavaScript?
  • JSON (JavaScript Object Notation) — це текстовий формат обміну даними, що легко читається як людиною, так і комп'ютером. Його використовують для передачі даних між клієнтом і сервером. Формат базується на синтаксисі об'єктів JavaScript, але підтримується в багатьох мовах програмування.

  • Основні особливості JSON:

  1. Ключі:

    • Завжди рядки.
    • Беруться в подвійні лапки ("").
  2. Значення:

    • Можуть бути: рядками, числами, логічними значеннями, масивами, об'єктами, null.
    • Не підтримує функції, undefined, NaN.
  • Приклад JSON:

    {
    "name": "Alice",
    "age": 25,
    "isStudent": false,
    "courses": ["Math", "Physics"],
    "address": { "city": "Kyiv", "zip": "01001" }
    }
    
  • Як працювати з JSON у JavaScript?

  1. Перетворення об'єкта у JSON (JSON.stringify):

    • Використовується для перетворення JavaScript-об'єкта в JSON-рядок.
    const user = {
      name: "Alice",
      age: 25,
      isStudent: false,
    };
    
    const jsonString = JSON.stringify(user);
    console.log(jsonString);
    // Виведе: '{"name":"Alice","age":25,"isStudent":false}'
  2. Перетворення JSON у об'єкт (JSON.parse):

    • Використовується для перетворення JSON-рядка у JavaScript-об'єкт.
    const jsonString = '{"name":"Alice","age":25,"isStudent":false}';
    
    const user = JSON.parse(jsonString);
    console.log(user);
    // Виведе: { name: 'Alice', age: 25, isStudent: false }
  • Робота з сервером:

    Передача даних у форматі JSON:

  1. Надсилання даних:

    • Використовуйте fetch із JSON.stringify для передачі JSON.
    const data = { name: "Alice", age: 25 };
    
    fetch("https://example.com/api", {
      method: "POST",
      headers: { "Content-Type": "application/json" },
      body: JSON.stringify(data),
    });
  2. Отримання даних:

    • Використовуйте fetch із JSON.parse для обробки відповіді.
    fetch("https://example.com/api")
      .then((response) => response.json())
      .then((data) => console.log(data));
  • Типові помилки:
  1. Неправильний формат JSON:

    const invalidJson = "{ name: 'Alice' }"; // Помилка: ключі та рядки без подвійних лапок
    JSON.parse(invalidJson); // Викине помилку
  2. Перетворення циклічного об'єкта:

    const obj = {};
    obj.self = obj;
    JSON.stringify(obj); // Викине помилку: Converting circular structure to JSON
  • Застосування JSON:

    • Обмін даними між клієнтом і сервером.
    • Збереження налаштувань у файлах чи локальному сховищі.
    • API для роботи з веб-сервісами.
18. Як виконується асинхронний код у JavaScript?
  • Асинхронний код у JavaScript виконується за допомогою подій, колбеків, промісів і async/await. Виконання базується на подійному циклі (Event Loop), що дозволяє обробляти асинхронні задачі поза основним потоком виконання.

  • Механізми асинхронного виконання:

  1. Події та Колбеки
  • Код виконується, коли завершується асинхронна операція (наприклад, таймер, запит до сервера).

  • Колбек-функції викликаються після завершення операції.

    setTimeout(() => {
      console.log("Асинхронно через 1 секунду");
    }, 1000);
    console.log("Цей код виконається першим");
    // Виведе:
    // Цей код виконається першим
    // Асинхронно через 1 секунду
  1. Проміси (Promises)

    • Promise представляє операцію, яка виконується асинхронно та може завершитися успішно або з помилкою.
    • Має методи .then і .catch для обробки результату.
    const promise = new Promise((resolve, reject) => {
      setTimeout(() => resolve("Дані отримано"), 1000);
    });
    
    promise
      .then((data) => console.log(data)) // Виведе: Дані отримано
      .catch((err) => console.error(err));
  2. async/await

    • Синтаксичний цукор для роботи з промісами.
    • Дозволяє писати асинхронний код так, ніби він синхронний.
    const fetchData = async () => {
      try {
        const response = await fetch(
          "https://jsonplaceholder.typicode.com/posts/1"
        );
        const data = await response.json();
        console.log(data);
      } catch (error) {
        console.error("Помилка:", error);
      }
    };
    
    fetchData();
  • Ключові поняття:
  1. Event Loop (Цикл подій):
  • Основний механізм, що дозволяє виконувати асинхронний код.

  • Розподіляє задачі між:

    • Call Stack (стек викликів): виконує синхронний код.
    • Task Queue (черга задач): для колбеків від setTimeout, DOM-подій.
    • Microtask Queue: для промісів та async/await.
  1. Microtasks vs. Macrotasks:
  • Microtasks (вищий пріоритет): Promise.then, MutationObserver.

  • Macrotasks: setTimeout, setInterval, I/O, події DOM.

    console.log("Початок");
    
    setTimeout(() => console.log("Macrotask"), 0);
    
    Promise.resolve().then(() => console.log("Microtask"));
    
    console.log("Кінець");
    
    // Виведе:
    // Початок
    // Кінець
    // Microtask
    // Macrotask
  • Приклади:

  1. Асинхронний ланцюжок:

    fetch("https://jsonplaceholder.typicode.com/posts/1")
      .then((response) => response.json())
      .then((data) => console.log(data))
      .catch((err) => console.error("Помилка:", err));
  2. Паралельне виконання:

    const promise1 = fetch("https://jsonplaceholder.typicode.com/posts/1");
    const promise2 = fetch("https://jsonplaceholder.typicode.com/posts/2");
    
    Promise.all([promise1, promise2])
      .then((responses) => Promise.all(responses.map((r) => r.json())))
      .then((data) => console.log(data));

Асинхронний код дозволяє виконувати тривалі операції без блокування головного потоку.

19. Що таке Event Loop (Цикл подій)?
  • Event Loop — це механізм в JavaScript, який відповідає за обробку асинхронних операцій.
  • Він працює так:
  1. Call Stack (Стек викликів): Зберігає функції, які виконуються.
  2. Task Queue (Черга завдань): Містить асинхронні колбеки (наприклад, setTimeout), готові до виконання.
  3. Microtask Queue (Черга мікрозавдань): Містить мікрозавдання, як-от Promise або MutationObserver.
  • Процес:

  • Якщо Call Stack порожній, Event Loop бере завдання з Microtask Queue (пріоритетно) або Task Queue й переміщує їх у Call Stack для виконання.

20. Що таке Call Stack (Стек викликів)?
  • Call Stack — це структура даних, яка працює за принципом LIFO (Last In, First Out) і використовується для відстеження виконання функцій у JavaScript.

    • Коли викликається функція, вона додається до вершини стеку.
    • Коли функція завершується, вона видаляється зі стеку.
    • Якщо функція викликає іншу функцію, та додається до стеку поверх попередньої.
  • Call Stack обробляє тільки синхронний код. Якщо стек переповнюється (наприклад, через рекурсію без базового випадку), це спричиняє помилку RangeError: Maximum call stack size exceeded.

21. Що таке Task Queue (Черга завдань)?
  • Task Queue — це черга, яка зберігає асинхронні завдання, готові до виконання, наприклад, колбеки з setTimeout, setInterval, або події DOM.

  • Коли Call Stack порожній, Event Loop бере завдання з Task Queue і додає його до стеку викликів для виконання.

  • Task Queue має нижчий пріоритет порівняно з Microtask Queue, тому мікрозавдання (наприклад, з Promises) обробляються першими, навіть якщо в Task Queue вже є готові завдання.

22. Що таке Microtask Queue (Черга мікрозавдань)?
  • Microtask Queue — це черга для завдань з високим пріоритетом, наприклад:

    • Колбеки з Promise (наприклад, .then, .catch, .finally).
    • Завдання з MutationObserver.
  • Після виконання кожної операції в Call Stack, Event Loop перевіряє Microtask Queue і виконує всі мікрозавдання, перш ніж перейти до Task Queue.

  • Це забезпечує швидку обробку мікрозавдань і робить їх пріоритетними над звичайними асинхронними завданнями.

23. Як ви працюєте з асинхронним кодом у JavaScript без використання async/await? Які інші підходи ви розглядаєте для роботи з асинхронністю?
  • Без async/await асинхронний код у JavaScript можна обробляти такими підходами:
  1. Callbacks (Колбеки):

    • Передача функції як аргумент для обробки результату.

    • Мінус: створює "callback hell", ускладнюючи читабельність.

    setTimeout(() => {
      console.log("Дані завантажені");
    }, 1000);
  2. Promises:

    • Використання then, catch, finally для обробки асинхронності.

    • Більш читабельний, ніж колбеки, але може бути громіздким для складних сценаріїв.

      Копіювати код
      fetch('/api/data')
      .then(response => response.json())
      .then(data => console.log(data))
      .catch(error => console.error(error));
  3. Event Listeners (Слухачі подій):

    • Реагування на асинхронні події через обробники, наприклад, addEventListener.

    • Використовується для роботи з DOM чи подіями введення користувача.

    button.addEventListener("click", () => {
      console.log("Кнопка натиснута");
    });
  4. RxJS (Reactive Extensions):

    • Використання бібліотеки для роботи з потоками даних через об'єкти Observable.

    • Підходить для складних асинхронних сценаріїв, як-от обробка кількох подій одночасно.

    const observable = from(fetch("/api/data"));
    observable.subscribe({
      next: (response) => console.log(response),
      error: (err) => console.error(err),
    });
24. Яка різниця між == і ===?
  • В JavaScript == і === відрізняються способом порівняння:
  1. == (Нестроге порівняння):

    • Виконує приведення типів (type coercion), тому значення можуть бути різних типів.
    "5" == 5; // true
    false == 0; // true
    null == undefined; // true
  2. === (Строге порівняння): Порівнює без приведення типів. Значення повинні бути одного типу.

    "5" === 5; // false
    false === 0; // false
    null === undefined; // false
  • Коротко:

    • Використовуйте ===, щоб уникнути неочікуваних результатів через приведення типів.
    • == підходить лише у випадках, коли ви точно розумієте, як працює приведення.
25. Що таке прототип у JavaScript?
  • Прототип у JavaScript — це механізм, за допомогою якого об'єкти можуть успадковувати властивості та методи від інших об'єктів.

  • Як це працює:

  1. Кожен об'єкт має внутрішнє посилання на свій прототип, яке називається [[Prototype]].

  2. Прототипом об'єкта може бути інший об'єкт або null.

  3. Коли ви намагаєтесь отримати доступ до властивості або методу об'єкта, JavaScript шукає їх у цьому об'єкті. Якщо не знаходить, переходить до прототипу й так далі в ланцюжку прототипів (prototype chain).

  • Приклад:

    function Person(name) {
      this.name = name;
    }
    
    Person.prototype.greet = function () {
      console.log(`Привіт, я ${this.name}`);
    };
    
    const user = new Person("Іван");
    user.greet(); // Привіт, я Іван
    • Person.prototype — це прототип для всіх об'єктів, створених через Person.
    • Метод greet доступний об'єкту user через його прототип.
  • Прототипне наслідування:

    const animal = {
      eat() {
        console.log("Їм");
      },
    };
    
    const dog = Object.create(animal);
    dog.bark = function () {
      console.log("Гав!");
    };
    
    dog.eat(); // Їм (успадковано з animal)
    dog.bark(); // Гав!
  • Ключові моменти:

    • Прототипи — це основа роботи з об'єктами у JavaScript.
    • Ланцюжок прототипів завершується null.
    • Object.getPrototypeOf(obj) дозволяє отримати прототип об'єкта.
26. У чому різниця між null та undefined?
  • null і undefined — це два різні типи даних в JavaScript, які обидва означають "відсутність значення", але вони використовуються в різних контекстах.
  1. null:

    • Це спеціальний об'єкт у JavaScript, що означає "відсутність значення" або "порожній об'єкт".

    • Його зазвичай використовують, щоб явно вказати на відсутність значення або на відсутність об'єкта.

    • Ініціалізується вручну.

    let user = null; // явно вказано, що значення відсутнє
  2. undefined:

    • Це примітивний тип в JavaScript, що означає, що змінна була оголошена, але їй не було присвоєно значення.
    • Змінні без значення автоматично мають тип undefined.
    • Також використовується як значення за умовчанням для неініціалізованих параметрів функцій.
    let user;
    console.log(user); // undefined
    
    function test(a) {
      console.log(a); // undefined, якщо параметр не передано
    }
    test();
  • Основні відмінності:

    • null — це об'єкт, явно призначений для вказівки на відсутність значення.
    • undefined — це значення, яке присвоюється змінній, коли їй не було надано значення або коли параметр функції не переданий.
  • Порівняння:

    • null == undefined — true (при порівнянні з == вони вважаються рівними через приведення типів).
    • null === undefined — false (при строгому порівнянні вони не однакові, бо мають різні типи).
27. Що таке контекст? Як можна змінювати контекст виконання функції?
  • Контекст виконання (execution context) — це середовище, в якому виконується JavaScript-код. Контекст визначає, які змінні, функції та об'єкти доступні в процесі виконання.

  • Існує кілька видів контексту:

  1. Глобальний контекст: Це початковий контекст, в якому запускається код (в браузері — це глобальний об'єкт window).

  2. Контекст функції: Кожен виклик функції створює новий контекст виконання, що дозволяє доступ до змінних і параметрів функції.

  3. Контекст об'єкта: Коли функція викликається як метод об'єкта, контекстом є цей об'єкт.

  • Як змінювати контекст виконання функції?
  1. this — це ключовий елемент контексту. Він вказує на об'єкт, що є контекстом виконання.

  2. Методи для зміни контексту:

    • call(): Викликає функцію з конкретним контекстом.
    function greet() {
      console.log(`Привіт, ${this.name}`);
    }
    
    const person = { name: "Іван" };
    greet.call(person); // Привіт, Іван
    • apply(): Теж викликає функцію з певним контекстом, але аргументи передаються у вигляді масиву.
    function sum(a, b) {
      console.log(this.name, a + b);
    }
    
    const person = { name: "Оля" };
    sum.apply(person, [2, 3]); // Оля 5
    • bind(): Створює нову функцію з прив'язаним контекстом, яку можна викликати пізніше.
    function show() {
      console.log(this.name);
    }
    
    const person = { name: "Петро" };
    const showPerson = show.bind(person);
    showPerson(); // Петро
  • Пояснення:

    • call() та apply() викликають функцію одразу з визначеним контекстом.
    • bind() створює нову функцію, яка завжди має певний контекст, що може бути викликана пізніше.

Зміна контексту важлива, коли потрібно працювати з методами, які викликаються в різних обставинах, або при роботі з колбеками та асинхронним кодом.

28. Що таке Promise? У яких випадках ви ним користуєтеся?
  • Promise— це об'єкт, який представляє результат асинхронної операції, яка може бути завершена або з успіхом, або з помилкою. Promise дозволяє працювати з асинхронним кодом більш зручним способом, ніж через колбеки.

  • Структура:

    • Pending — стан, коли операція ще не завершена.
    • Resolved (Fulfilled) — стан, коли операція успішно завершена.
    • Rejected — стан, коли операція завершена з помилкою.
  • Приклад створення:

    let promise = new Promise((resolve, reject) => {
      let success = true;
    
      if (success) {
        resolve("Операція успішна");
      } else {
        reject("Щось пішло не так");
      }
    });
    
    promise
      .then((result) => console.log(result)) // Обробка успіху
      .catch((error) => console.log(error)); // Обробка помилки
  • Переваги:

    • Читабельність: Ланцюжок .then() дозволяє більш зручно обробляти асинхронні операції.
    • Помилки: Легше обробляти помилки через .catch().
    • Кілька операцій: Легко працювати з кількома асинхронними задачами одночасно через Promise.all() або Promise.race().

Promise робить асинхронний код більш структурованим і менш громіздким порівняно з використанням колбеків.

29. Які особливості об’єктноорієнтованого програмування у JavaScript?
  • Об'єктноорієнтоване програмування (ООП) у JavaScript має кілька особливостей, оскільки мова не є класично об'єктноорієнтованою, як, наприклад, Java або C#. Однак вона підтримує об'єктноорієнтовані концепції через механізм прототипів і з введенням класів у ES6. Ось основні особливості ООП у JavaScript:
  1. Прототипне наслідування (Prototype-based Inheritance):

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

    • Коли ви звертаєтеся до властивості об'єкта, JavaScript спочатку шукає її в самому об'єкті, а потім переходить до його прототипу.

    const person = {
      name: "Іван",
      greet() {
        console.log(`Привіт, я ${this.name}`);
      },
    };
    
    const user = Object.create(person);
    user.name = "Оля";
    user.greet(); // Привіт, я Оля
  2. Функції як конструктори:

    • У JavaScript функції можуть бути використані як конструктори об'єктів. Це дозволяє створювати екземпляри об'єктів із певними властивостями та методами.
    function Person(name, age) {
      this.name = name;
      this.age = age;
    }
    
    const user = new Person("Іван", 25);
    console.log(user.name); // Іван
  3. Класи (ES6+ класова синтаксична конструкція):

    • З введенням ES6, JavaScript отримав класову синтаксис для створення об'єктів. Це полегшує створення класів і працює на основі прототипного наслідування.
    class Person {
      constructor(name, age) {
        this.name = name;
        this.age = age;
      }
    
      greet() {
        console.log(`Привіт, я ${this.name}`);
      }
    }
    
    const user = new Person("Іван", 25);
    user.greet(); // Привіт, я Іван
  4. Методи та властивості:

    • Об'єкти можуть мати методи (функції, прив'язані до об'єктів) та властивості (дані).
    • Методи можуть бути визначені за допомогою класів або функцій-конструкторів.
    const person = {
      name: "Іван",
      greet() {
        console.log(`Привіт, я ${this.name}`);
      },
    };
    person.greet(); // Привіт, я Іван
  5. Інкапсуляція:

    • У JavaScript є можливість інкапсулювати дані, використовуючи закриті або приватні властивості за допомогою замикань. З ES2022 також з'явилася підтримка приватних полів у класах через #.
    class Person {
      #name;
    
      constructor(name) {
        this.#name = name;
      }
    
      getName() {
        return this.#name;
      }
    }
    
    const person = new Person("Іван");
    console.log(person.getName()); // Іван
  6. Поліморфізм:

    • JavaScript підтримує поліморфізм через перезапис методів. Це означає, що різні об'єкти можуть мати однакові методи, але з різною реалізацією.
    class Animal {
      speak() {
        console.log("Робить звук");
      }
    }
    
    class Dog extends Animal {
      speak() {
        console.log("Гав!");
      }
    }
    
    const dog = new Dog();
    dog.speak(); // Гав!
  7. Абстракція:

    • Абстракція в JavaScript реалізується через класові та функціональні методи, що дозволяє приховувати складність реалізації і зберігати лише важливу інформацію для користувача.
    • Абстракція може бути досягнута через інтерфейси або базові класи, хоча JavaScript не має явної підтримки інтерфейсів, як в інших мовах.
  8. Метод new:

    • Ключове слово new використовується для створення екземплярів класів чи функцій-конструкторів, що ініціалізує новий об'єкт і встановлює прототип.
    Копіювати код
    function Person(name) {
    this.name = name;
    }
    
    const person = new Person('Іван');
  • Підсумок:

    • Прототипне наслідування замість класичного.
    • Функції-конструктори для створення об'єктів.
    • ES6 класи спрощують синтаксис для створення об'єктів та наслідування.
    • Можливість реалізації інкапсуляції та поліморфізму.
    • Абстракція через методи класів та замикання.

JavaScript поєднує елементи класичного ООП з прототипним підходом, що дозволяє використовувати різні стилі програмування в залежності від задачі.

30. Як з JS-коду звернутись до HTML-елемента та змінити його текст?
  • Щоб звернутися до HTML-елемента та змінити його текст у JavaScript, можна використовувати різні методи доступу до елементів DOM.

  • Приклад:

    • Використовуємо getElementById(), querySelector() або інші методи для доступу до елемента.
    • Змінюємо текст елемента за допомогою властивості textContent або innerText.
  • Приклад з getElementById():

    <!DOCTYPE html>
    <html lang="uk">
      <head>
        <meta charset="UTF-8" />
        <title>Зміна тексту</title>
      </head>
      <body>
        <p id="example">Старий текст</p>
        <script>
          // Отримуємо елемент за ID
          const element = document.getElementById("example");
    
          // Змінюємо текст
          element.textContent = "Новий текст";
        </script>
      </body>
    </html>
  • Приклад з querySelector():

    <!DOCTYPE html>
    <html lang="uk">
      <head>
        <meta charset="UTF-8" />
        <title>Зміна тексту</title>
      </head>
      <body>
        <p class="example">Старий текст</p>
        <script>
          // Отримуємо елемент за класом
          const element = document.querySelector(".example");
    
          // Змінюємо текст
          element.textContent = "Новий текст";
        </script>
      </body>
    </html>
  • Різниця між textContent і innerText:

    • textContent: Оновлює текст у елементі, включаючи прихований текст, але не виконує рендеринг CSS.

    • innerText: Оновлює текст, враховуючи стилі CSS (наприклад, схований текст не буде видимим).

Обидва підходи працюють для зміни тексту, але textContent — це більш швидкий і загальний спосіб.

31. Що таке деструктуризація?
  • Деструктуризація в JavaScript — це синтаксис, який дозволяє розпаковувати значення з масивів або властивості з об'єктів у окремі змінні. Це скорочує код і робить його більш зрозумілим.
  1. Деструктуризація масивів
  • Розпаковує значення елементів масиву в окремі змінні за позицією.

  • Приклад:

    const numbers = [10, 20, 30];
    const [a, b, c] = numbers;
    
    console.log(a); // 10
    console.log(b); // 20
    console.log(c); // 30
  1. Деструктуризація об'єктів
  • Розпаковує значення властивостей об'єкта в змінні за іменами ключів.

  • Приклад:

    const user = { name: "Evan", age: 25 };
    const { name, age } = user;
    
    console.log(name); // Evan
    console.log(age); // 25
  1. Деструктуризація в функціях
  • Дозволяє передавати об'єкти або масиви у функцію і розпаковувати їх прямо в параметрах.

    • Масиви:
    function sum([a, b]) {
      return a + b;
    }
    console.log(sum([10, 20])); // 30
    • Об'єкти:
    function greet({ name, age }) {
      console.log(`Привіт, ${name}, тобі ${age} років.`);
    }
    greet({ name: "Evan", age: 25 });
  • Переваги:

    • Зменшує кількість коду.
    • Полегшує роботу з вкладеними структурами.
    • Підвищує читабельність.
  • Деструктуризація — це потужний інструмент, який широко використовується у сучасному JavaScript.

32. Що буде, якщо звернутись до елемента масива, якого немає за індексом?
  • Якщо звернутися до елемента масиву за індексом, якого не існує, JavaScript поверне undefined.

  • Причина:

    • У JavaScript масиви є об'єктами, і доступ до елементів масиву працює через властивості об'єкта. Якщо властивість (тобто індекс) не існує, результатом буде undefined.
33. У чому різниця між for..of та for...in?
  • for...of і for...in використовуються для ітерації, але мають різне призначення та працюють з різними типами даних.
  1. for...of
  • Ітерує значення ітерабельних об'єктів, таких як масиви, рядки, об'єкти типу Map, Set, або об'єкти з реалізованим методом Symbol.iterator.

    • Приклад:
    const array = ["a", "b", "c"];
    for (const value of array) {
      console.log(value); // Виведе: 'a', 'b', 'c'
    }
    • Особливості:

      • Підходить для роботи з масивами та іншими ітерабельними об'єктами.
      • Використовує значення елементів.
      • Не підходить для ітерації по об'єктах з властивостями.
  1. for...in
  • Ітерує ключі (властивості) об'єкта або індекси масиву.

    • Приклад з об'єктом:
    const obj = { name: "Іван", age: 25 };
    for (const key in obj) {
      console.log(key); // Виведе: 'name', 'age'
    }
    • Приклад з масивом:
    const array = ["a", "b", "c"];
    for (const index in array) {
      console.log(index); // Виведе: '0', '1', '2'
    }
    • Особливості:

      • Використовується для ітерації по об'єктах.
      • Повертає ключі об'єкта або індекси масиву як рядки.
      • Не рекомендується для масивів, оскільки включає властивості прототипу.
  • Висновок:

    • for...of: Використовуйте для роботи з масивами та іншими ітерабельними об'єктами.
    • for...in: Використовуйте для ітерації по властивостях об'єкта. Не підходить для масивів.
34. Навіщо використовується оператор &&?
  • Оператор && (логічне І) в JavaScript використовується для перевірки логічних умов і короткого замикання. Його основне призначення — повертати перше хибне значення або останнє істинне.

  • Основні випадки використання:

  1. Перевірка кількох умов:

    • Повертає true, якщо всі операнди істинні.
    • Якщо хоча б один операнд хибний, повертає цей операнд.
    const a = true;
    const b = false;
    
    console.log(a && b); // false
    console.log(a && true); // true
  2. Коротке замикання:

    • Якщо перший операнд хибний, далі умови не перевіряються, і повертається його значення.
    • Якщо перший операнд істинний, обчислюється і повертається другий.
    const result = false && console.log("Не виконається"); // false
    const value = true && "Результат"; // 'Результат'
  3. Умовне виконання коду:

    • Використовується для виклику функцій або виконання дій лише при істинності умови.
    const user = { loggedIn: true };
    user.loggedIn && console.log("Користувач увійшов"); // 'Користувач увійшов'
  4. Використання в присвоєнні значень:

    • Якщо перший операнд істинний, результатом буде другий.
    const value = true && "Hello"; // 'Hello'
    const empty = false && "World"; // false
  5. Повернення значень:

    • && не просто повертає true або false. Він повертає значення одного з операндів.

    • Працює з будь-якими типами, не лише з булевими.

    • Приклад:

    console.log("a" && "b"); // 'b' (останнє істинне значення)
    console.log(false && "b"); // false (перше хибне значення)
    console.log("a" && 0); // 0 (перше хибне значення)
  • Висновок:

    • Оператор && корисний для:

      • Перевірки складених умов.
      • Зупинки виконання при хибному значенні (коротке замикання).
      • Умовного виконання виразів.
35. Навіщо використовується оператор ||?
  • Оператор || (логічне АБО) в JavaScript використовується для перевірки логічних умов і короткого замикання. Його основна мета — повертати перше істинне значення або останнє хибне.

  • Основні випадки використання:

  1. Перевірка кількох умов:

    • Повертає true, якщо хоча б один операнд істинний.
    • Якщо всі операнди хибні, повертає останнє хибне значення.
    const a = true;
    const b = false;
    
    console.log(a || b); // true
    console.log(b || false); // false
  2. Коротке замикання:

    • Якщо перший операнд істинний, далі умови не перевіряються, і повертається його значення.
    • Якщо перший операнд хибний, обчислюється і повертається другий.
    const result = true || console.log("Не виконається"); // true
    const value = false || "Результат"; // 'Результат'
  3. Значення за замовчуванням:

    • Використовується для задання дефолтного значення, якщо перше значення хибне.
    const userName = "" || "Анонім"; // 'Анонім'
    const number = 0 || 42; // 42
  4. Умовне виконання коду:

    • Логічне АБО дозволяє виконати альтернативну дію, якщо перша умова не спрацювала.
    const isAuthorized = false;
    isAuthorized || console.log("Доступ заборонено"); // 'Доступ заборонено'
  • Повернення значень:

    • || не обмежується булевими значеннями. Він повертає перше істинне значення або останнє хибне.

    • Приклади:

    console.log("a" || "b"); // 'a' (перше істинне)
    console.log(false || "b"); // 'b' (перше істинне)
    console.log(null || undefined || 0); // 0 (останнє хибне)
  • Висновок:

    • Оператор || корисний для:

      • Перевірки чи хоча б одна умова виконується.
      • Встановлення значень за замовчуванням.
      • Короткого замикання для оптимізації виконання коду.
36. Навіщо використовується оператор !!?
  • Оператор !! у JavaScript використовується для перетворення будь-якого значення в його булевий еквівалент. Це простий спосіб привести значення до true або false.

  • Як працює:

  1. Перший !: Інвертує значення. Перетворює його на булеве, якщо це ще не було зроблено, і змінює на протилежне (істинне → хибне, хибне → істинне).
  2. Другий !: Знову інвертує значення, повертаючи початкову логіку, але вже у булевій формі.
  • Приклади:

    • Приведення до булевого типу:
    console.log(!!0); // false (0 вважається "хибним")
    console.log(!!1); // true (1 вважається "істинним")
    console.log(!!""); // false (порожній рядок — "хибний")
    console.log(!!"hello"); // true (непорожній рядок — "істинний")
    console.log(!!null); // false
    console.log(!!undefined); // false
    console.log(!!{}); // true (об'єкти завжди "істинні")
    console.log(!![]); // true (масиви завжди "істинні")
  • Для чого використовується:

  1. Приведення до булевого типу:

    • Використовується для явного переведення значення в булевий тип в умовах або перевірках.
    const isActive = !!someVariable;
  2. Перевірка істинності значення:

    • Зручно для перевірки, чи значення існує або чи є воно "істинним".
    if (!!userName) {
      console.log("Ім'я користувача задано");
    }
  3. Явна демонстрація булевого результату:

    • Використовується, коли важливо явно показати, чи значення є істинним або хибним.
    const isValid = !!(age >= 18); // true, якщо вік >= 18
  • Висновок:

    • Оператор !! ефективно перетворює будь-яке значення у булеве. Це зручний інструмент для перевірок, умов та обробки даних у коді.
37. Навіщо використовується оператор !?
  • Оператор ! (логічне НЕ) у JavaScript використовується для інверсії булевого значення. Він змінює істинне значення на хибне і навпаки.

  • Основні випадки використання:

  1. Інверсія булевого значення:
  • Оператор ! змінює логіку булевого виразу.

    console.log(!true); // false
    console.log(!false); // true
  1. Перетворення в булевий тип:
  • Якщо значення не є булевим, оператор ! автоматично приводить його до булевого типу, а потім інвертує.

    console.log(!0); // true (0 вважається "хибним")
    console.log(!"hello"); // false (рядок вважається "істинним")
    console.log(!undefined); // true
  1. Умовні перевірки:
  • Використовується для перевірки хибності значення.

    const isValid = false;
    if (!isValid) {
      console.log("Не валідно");
    }
  1. Зворотна логіка:
  • Полегшує написання умов, які мають бути виконані при хибних значеннях.

    const user = null;
    if (!user) {
      console.log("Користувач не знайдений");
    }
  • Приклади з інверсією:

    • Інверсія:
    const isOnline = false;
    console.log(!isOnline); // true (зворотне значення)
    • Вкладені перевірки:
    const isEmpty = !array.length; // true, якщо масив порожній
  • Висновок:

    • Оператор ! інвертує булеве значення та дозволяє зручно перевіряти хибність або істинність умов. Це базовий інструмент для роботи з логічними виразами.
38. Які значення в JS є хибними?
  • У JavaScript до хибних значень (falsy values) належать ті, що при приведенні до булевого типу стають false.

  • Перелік хибних значень:

  1. false— логічне значення "хибність".
  2. 0 — числовий нуль.
  3. -0 — від'ємний нуль (рідко використовується, але технічно існує).
  4. NaN — "не число".
  5. "" — порожній рядок (подвійні лапки).
  6. '' — порожній рядок (одинарні лапки).
  7. (``) — порожній рядок (шаблонні літерали).
  8. null — відсутність значення.
  9. undefined — невизначене значення.
  • Приклади:

    console.log(Boolean(false)); // false
    console.log(Boolean(0)); // false
    console.log(Boolean("")); // false
    console.log(Boolean(null)); // false
    console.log(Boolean(undefined)); // false
    console.log(Boolean(NaN)); // false
39. Які значення в JS є правдивими?
  • У JavaScript правдиві значення (truthy values) — це ті, які при приведенні до булевого типу стають true. Це всі значення, які не входять до списку хибних (falsy values).

  • Перелік типових правдивих значень:

  1. Непорожні рядки:

    console.log(Boolean("hello")); // true
    console.log(Boolean(" ")); // true (навіть якщо це пробіл)
    console.log(Boolean("0")); // true
  2. Числа, крім 0:

    console.log(Boolean(42)); // true
    console.log(Boolean(-42)); // true
    console.log(Boolean(Infinity)); // true
    console.log(Boolean(-Infinity)); // true
  3. Об'єкти (включаючи порожні):

    console.log(Boolean({})); // true
    console.log(Boolean([])); // true
  4. Функції:

    console.log(Boolean(function () {})); // true
  5. Спеціальні значення:

    • Symbol() — завжди істинний.
    • Будь-який BigInt, відмінний від 0n.
40. Як перевірити, чи є значення хибним?
  • Щоб перевірити, чи є значення хибним (falsy) у JavaScript, можна скористатися приведенням до булевого типу. Ось кілька способів:
  1. Використання ! (логічного НЕ):

    if (!value) {
      console.log("Значення є хибним");
    }
    • Логічне НЕ інвертує булеве значення, і для хибного результату умова виконається.
  2. Використання Boolean():

    if (!Boolean(value)) {
      console.log("Значення є хибним");
    }
    • Функція Boolean() явно перетворює значення в булеве. Якщо Boolean(value) повертає false, значення хибне.
  3. Перевірка через подвійний !!:

    console.log(!!value); // true для правдивих, false для хибних
    • Подвійний ! використовується для явного приведення значення до булевого типу. Якщо результат false, значення хибне.
  4. Список хибних значень:

    • Можна порівняти значення з відомими falsy values:
    if (
      value === false ||
      value === 0 ||
      value === "" ||
      value === null ||
      value === undefined ||
      Number.isNaN(value)
    ) {
      console.log("Значення є хибним");
    }
  • Приклади:

    console.log(!0); // true (0 є хибним)
    console.log(!""); // true (порожній рядок є хибним)
    console.log(!undefined); // true (undefined є хибним)
    console.log(!42); // false (число 42 є правдивим)
    console.log(![]); // false (масив є правдивим)
  • Висновок:

    • Найзручніший спосіб перевірити, чи значення хибне — використати !value.
41. Що таке DOM?
  • DOM (Document Object Model) — це програмний інтерфейс для веб-документів, який надає структуру HTML або XML документа у вигляді дерева об'єктів. DOM дозволяє програмам та скриптам взаємодіяти з документами, змінюючи їх вміст, структуру та стиль.

  • Основні моменти:

  1. Представлення документа: DOM представляє HTML або XML документ як дерево елементів, де кожен вузол дерева є об'єктом, що відповідає певній частині документа (наприклад, тегу, атрибуту або тексту).

  2. Динамічна взаємодія: Через DOM можна змінювати веб-сторінки на льоту. За допомогою JavaScript можна додавати, видаляти або змінювати елементи HTML, обробляти події (кліки, введення даних) та змінювати стиль елементів.

  3. Структура дерева: DOM є деревом з кореневим елементом <html>, що містить елементи <head> та <body>, а ті, у свою чергу, містять інші елементи (наприклад, <div>, <p>, <span>).

  • Висновок:
    • DOM є ключовим механізмом для взаємодії з веб-сторінками. Він дозволяє програмно змінювати структуру і зміст HTML-документів, що робить веб-сторінки динамічними та інтерактивними.
42. Що таке розповсюдження події (Event Propogation)?
  • Розповсюдження події (Event Propagation) в JavaScript — це процес, за якого подія, що сталася на одному елементі, передається іншим елементам в DOM-дереві. Розповсюдження події можна розділити на два основні етапи:
  1. Фаза захоплення (Capturing phase):

    • Це перша фаза, коли подія "захоплюється" від кореня документа і йде вниз через усі батьківські елементи до того елемента, на якому була ініційована подія. Цей етап рідко використовується.
  2. Фаза цільового елемента (Target phase):

    • Це етап, коли подія потрапляє безпосередньо на елемент, на якому вона була ініційована (наприклад, натискання на кнопку). Тепер подія обробляється саме на цьому елементі.
  3. Фаза спливання (Bubbling phase):

    • Після обробки на цільовому елементі подія "спливає" (bubbles) до батьківських елементів і вище, поки не досягне кореня документа. Це основний етап, який найчастіше використовується для обробки подій.
  • Висновок:

    • Розповсюдження події дозволяє ефективно управляти тим, як подія поширюється по DOM-дереву. Ви можете використовувати фазу захоплення, цільову фазу або спливання для обробки подій, а також контролювати це за допомогою методів stopPropagation() і stopImmediatePropagation().
43. Чому результат порівняння двох схожих об'єктів є false?
  • У JavaScript результат порівняння двох схожих об'єктів за допомогою оператора == або === зазвичай є false, навіть якщо ці об'єкти виглядають схожими, через те, як працює порівняння об'єктів у JavaScript.

  • Причина:

    • Об'єкти в JavaScript порівнюються за посиланням, а не за їхнім вмістом. Тобто, коли ви порівнюєте два об'єкти, перевіряється чи вони вказують на один і той самий об'єкт в пам'яті, а не чи їхні властивості однакові.
  • Приклад:

    const obj1 = { name: "John", age: 30 };
    const obj2 = { name: "John", age: 30 };
    
    onsole.log(obj1 == obj2); // false
    onsole.log(obj1 === obj2); // false
    • Обидва об'єкти obj1 та obj2 мають однакові властивості, але це різні об'єкти в пам'яті. Оператор == та === порівнюють посилання на об'єкти, тому результат порівняння буде false.
  • Пояснення:

    • == — порівнює два значення, приводячи їх до спільного типу (для об'єктів це буде порівняння посилань).
    • === — порівнює два значення без приведення типів, тому також порівнює посилання для об'єктів.
  • Як порівняти об'єкти по вмісту?

    • Якщо потрібно порівняти об'єкти за їхніми властивостями (по вмісту), вам слід вручну порівнювати кожну властивість або використати спеціальні методи, такі як JSON.stringify():
    console.log(JSON.stringify(obj1) === JSON.stringify(obj2)); // true
    • Але зверніть увагу, що цей метод не працює для порівняння складніших об'єктів, таких як об'єкти з методами чи циклічні посилання.
44. Який найшвидший спосіб перетворення рядка на число?
  • Найшвидший спосіб перетворення рядка на число в JavaScript — це використання унарного оператора +.

  • Приклад:

    const str = "42";
    const num = +str;
    console.log(num); // 42
  • Цей метод є дуже швидким і ефективним, оскільки він використовує внутрішнє перетворення типів JavaScript.

  • Альтернативи:

  1. parseInt():
  • Перетворює рядок на ціле число.

    const num = parseInt(str, 10); // 42
  • Однак це повільніше, ніж унарний оператор +, через додаткову обробку (встановлення бази для чисел).

  1. parseFloat():
  • Перетворює рядок на число з плаваючою точкою.

    const num = parseFloat(str); // 42
  • Також повільніше, ніж унарний оператор.

  • Висновок:

    • Унарний оператор + є найшвидшим і найбільш ефективним способом перетворення рядка на число.
45. Як записати кілька виразів в один рядок?
  • Щоб записати кілька виразів в один рядок у JavaScript, можна використовувати крапку з комою ; для розділення виразів.

  • Приклад:

    let a = 5;
    let b = 10;
    let c = a + b;
    console.log(c);
  • Тут ми об’єднали три вирази в одному рядку, розділивши їх крапками з комами.

  • Важливо:

    • Використання крапок з комами дозволяє писати кілька інструкцій в одному рядку, але важливо не забувати про роздільники для уникнення помилок.
    • Це не завжди є рекомендованим підходом, оскільки може погіршити читабельність коду, але в коротких ситуаціях це працює.
46. Що таке підняття (Hoisting)?
  • Підняття (Hoisting) — це механізм у JavaScript, при якому оголошення змінних і функцій "піднімаються" на початок своєї області видимості під час виконання коду, навіть якщо вони знаходяться після використання.

  • Основні моменти:

  1. Оголошення змінних та функцій піднімаються: JavaScript піднімає лише оголошення, а не ініціалізацію змінних або значення функцій.

  2. Функції: У разі функцій, які оголошуються через function (function declaration), піднімається і сама функція разом із її тілами.

  3. Змінні: У разі змінних, оголошених через var, піднімається тільки оголошення, але не їх ініціалізація (значення). У результаті, змінна буде існувати, але її значення буде undefined до моменту присвоєння.

  • Приклад 1: Функції

    console.log(greet()); // "Hello!"
    function greet() {
      return "Hello!";
    }
  • У цьому прикладі виклик greet() працює, навіть якщо викликається до її оголошення. Це відбувається через підняття, оскільки функція повністю піднімається разом зі своїм тілом.

  • Приклад 2: Змінні

    console.log(a); // undefined
    var a = 5;
    console.log(a); // 5
  • У цьому прикладі змінна a спочатку матиме значення undefined, оскільки лише оголошення (але не ініціалізація) змінної піднімається. Після присвоєння значення a стає 5.

  • Підняття з let та const

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

    console.log(a); // ReferenceError: Cannot access 'a' before initialization
    let a = 5;
  • Тут виклик змінної до її ініціалізації викличе помилку, тому що змінна знаходиться в "мертвій зоні".

  • Висновок:

    • Підняття дозволяє використовувати функції та змінні до їх фактичного оголошення в коді, але для змінних, оголошених через var, значення буде undefined до присвоєння, а для змінних, оголошених через let або const, це призведе до помилки, якщо спробувати доступитися до них до ініціалізації.
47. Що таке область видимості (Scope)?
  • Область видимості (Scope) в JavaScript — це контекст, у якому визначаються змінні, функції та інші ідентифікатори. Область видимості визначає, де саме в коді можна звертатися до цих змінних або функцій.

  • Типи областей видимості:

  1. Глобальна область видимості:

    • Це область, яка доступна в будь-якому місці вашого коду.
    • Змінні та функції, оголошені поза будь-якими функціями або блоками, мають глобальну область видимості.
    let globalVar = "I'm global";
    
    function test() {
      console.log(globalVar); // Доступ до глобальної змінної
    }
    
    test();
    console.log(globalVar); // Також доступно поза функцією
  2. Область видимості функції (Function Scope):

    • Кожна функція має свою область видимості, і змінні, оголошені всередині функції, доступні тільки в цій функції.
    function test() {
      let localVar = "I'm local";
      console.log(localVar); // Доступ до localVar всередині функції
    }
    
    test();
    console.log(localVar); // Помилка: localVar не існує за межами функції
  3. Область видимості блоку (Block Scope):

    • Змінні, оголошені за допомогою let або const, мають область видимості на рівні блоку (в межах {}).
    if (true) {
      let blockVar = "I'm block-scoped";
      console.log(blockVar); // Доступно всередині блоку
    }
    
    console.log(blockVar); // Помилка: blockVar не доступно поза блоком
  4. Лексичний Scope (Lexical Scope):

    • Лексичний scope визначається на етапі написання коду, а не виконання. Це означає, що область видимості функцій визначається тим, де вони були оголошені, а не тим, де вони викликаються.
    function outer() {
      let outerVar = "I'm outer";
    
      function inner() {
        console.log(outerVar); // Доступ до outerVar через лексичний scope
      }
    
      inner();
    }
    
    outer();
  • Важливі моменти:

    • Глобальні змінні доступні в усьому коді, але їх використання може призвести до проблем, якщо імена змінних збігаються.
    • Функціональні змінні доступні тільки в межах функції.
    • Змінні в межах блоку з let і const доступні лише в тому блоці, в якому вони оголошені.
  • Підсумок:

    • Область видимості визначає, де змінні і функції можуть бути використані. Правильне розуміння області видимості допомагає уникати помилок, пов'язаних з доступом до змінних і функцій у некоректних місцях.
48. Навіщо використовується директива use strict?
  • Coming Soon... 😎

About

Найпопулярніші запитання та відповіді на співбесіді з JavaScript

Topics

Resources

License

Code of conduct

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published