Підготуйтеся до співбесіди з JavaScript, вивчивши питання, які часто ставлять на технічних інтерв'ю для позицій junior frontend і junior javascript розробник. Ця сторінка містить короткі відповіді на важливі питання та посилання на ресурси для додаткового вивчення. Перевірте знання основ мови, роботи зі змінними, функціями, об'єктами, масивами та іншими ключовими концепціями JavaScript, щоб бути готовим до будь-яких питань на співбесіді.
Нижче наведено питання по темі Javascript (джерело), які часто задають на співбесіді. Прочитавши питання, постарайтеся відповісти на нього так, як ви це зробили б під час свого інтерв'ю. Під питанням ви знайдете відповідь та посилання на джерела, які розкривають тему докладніше.
1) Опишіть прийом делегування подій у JS.
Переглянути відповідь
У разі, коли нам потрібно обробити подію на кількох елементах, що мають спільного предка, ми "вішаємо" прослуховувач не на елементи, а на предка. Після, за допомогою event.target, ми можемо отримати доступ до конкретного елемента, на якому було скоєно цільову подію та обробити її.
Докладніше тут:
2) Опишіть, як працює this в JavaScript. Наведіть приклад того, як робота з this змінилася в ES6.
Переглянути відповідь
this — Посилання на об'єкт, у контексті якого виконується функція. Іншими словами, якщо всередині функції є звернення типу this.ім'я_властивості це означає, що ми звертаємося до властивості об'єкта в контексті якого ця функція виконується. Цей механізм дозволяє писати функції, які легко перевикористовуються. Судіть самі:
function getName() {
return this.name;
}
var sally = { name: ‘Sally’};
getName.call(sally); // Sally
var megan = { name: ‘Megan’};
getName.call(megan); // ‘Megan
Тут функція getName нічого не знає про об'єкт у контексті якого вона буде викликана, проте чудово виконує свій обов'язок. Важливий момент: контекст виконання прив'язується в момент виклику функції (рядок getName.call(sally)). ES6 була додана стрілочна функція, контекст виконання якої встановлюється не в момент виклику функції, як у прикладі вище, а в момент визначення самої функції.
var getName = () => {
return this.name;
}
var sally = { name: 'Sally'};
getName.call(sally); // undefined
Тут отримуємо undefined замість імені, тому що функція визначена в глобальному скоупі, а в нестрогому режимі, в момент визначення стрілочної функції, її this буде вказувати на window (у браузері). У window змінна name не визначена, звідси і undefined. Явне визначення контексту виклику (.call()) зі стрілочними функціями не працює.
Докладніше тут:
3) Опишіть, як працює прототипно-орієнтована модель спадкування в JS.
Переглянути відповідь
У плані наслідування JavaScript працює лише з однією сутністю: об'єктами. Кожен об'єкт має внутрішнє посилання інший об'єкт, названий його прототипом. Об'єкт-прототип також має свій власний прототип і так далі, поки ланцюжок не завершиться об'єктом, у якого властивість prototype дорівнює null. За визначенням, null не має прототипу і є завершальною ланкою в ланцюжку прототипів. Спадкування з ланцюжком прототипів
При спробі отримати доступ до будь-якої властивості об'єкта, властивість спочатку шукається в самому об'єкті, потім у ланцюжку прототипів. Пошук ведеться до тих пір, поки не знайдено властивість з іменем, що збігається, або не буде досягнутий кінець ланцюжка прототипів.
Докладніше тут:
4) У чому різниця між значеннями: null, undefined або undeclared? Як би ви провели перевірку на ці значення?
Переглянути відповідь
null - Порожнє значення,
undefined - Невизначене значення
undeclared - Змінна не була оголошена, виклик її викличе помилку, виклик typeof покаже undefined (Для реалізації перевірки). Для тестової змінної «a» перевірка може бути реалізована наступним чином:
typeof a !== 'undefined' && Boolean(a)
Докладніше тут:
5) Що таке замикання в JS, і як/навіщо його використовують?
Переглянути відповідь
Замикання - прийом при якому функція має доступ до лексичної області видимості своєї функції-обгортки, яка була виконана раніше, але не може бути вивільнена з пам'яті через те, що її власна область видимості ще використовується іншою функцією. Найкраще сказане буде видно на прикладі, приклад з коментарями тут: https://codepen.io/CHMSupport/pen/JjypeMd?editors=0010
Докладніше тут:
6) Які конструкції мови ви використовуєте для перебору властивостей об'єкта та елементів масиву?
Переглянути відповідь
Для перебору всіх (власних та успадкованих) властивостей об'єкта використовується цикл for..in. Для простого перебору елементів масиву найчастіше використовується функція Array.forEach().
Докладніше тут:
7) Опишіть основну різницю між методами Array.forEach () і Array.map(), у яких випадках ви б застосували кожен із них?
Переглянути відповідь
Метод Array.forEach() перебирає всі елементи масиву і для кожного викликає передану в кожну функцію callback. Після відпрацювання нічого не повертає, при зміні елемента масиву в callback функції зміни відображаються у вихідному масиві. Array.map() перебирає всі елементи масиву і кожного викликає передану callback функцію. Після відпрацювання повертає новий масив, рівний по довжині вихідного, який містить у собі перетворені елементи масиву. При зміні елемента масиву в callback функції зміни не відображаються у вихідному масиві.
Докладніше тут:
8) Для чого використовують анонімні функції в JS?
Переглянути відповідь
Анонімними називаються функції, які не мають власного імені, як наслідок, їх не можна спочатку оголосити, а потім викликати. Найчастіше такі функції використовують у якості callback функцій.
Докладніше тут:
9) У чому різниця між host objects і native objects?
Переглянути відповідь
Native objects — об'єкти, визначені специфікацією ECMAScript, наприклад, Object (constructor), Date, Math.
Host objects— об'єкти, роль яких у створенні виконавчого оточення для ECMAScript, наприклад, window, document, location, history.
Докладніше тут:
10) У чому різниця між Function Declaration і Function Expression у JavaScript?
Переглянути відповідь
Function Declaration (функція, оголошена у потоці коду) – класична форма оголошення функції.
function sum(a, b) {
return a + b;
}
Function Expression (функціональний вираз) – альтернативний синтаксис для оголошення функції.
var sum = function(a, b) {
return a + b;
}
По суті, вони роблять те саме, але функції, оголошені як Function Declaration можуть бути викликані раніше їх місця оголошення в коді (hoisting), а Function Expression ні.
sum(2, 4);
function sum(a, b) {
return a + b;
}
Докладніше тут:
11) Опишіть, що роблять Function.call і Function.apply. У чому полягає основна різниця між ними?
Переглянути відповідь
Обидва методи використовуються для вказівки контексту при виклику функції, до якої застосовуються. Відрізняються синтаксисом, apply більш гнучка.
Докладніше тут:
12) За що відповідає Function.prototype.bind ?
Переглянути відповідь
Function.prototype.bind - створює нову функцію, яка при викликі встановлює як контекст виконання (this) надане значення, тобто відповідає за виклик функцій з іншим контекстом.
Докладніше тут:
13) За що відповідають і в чому полягає різниця між feature detection, feature inference і User Agent String ?
Переглянути відповідь
- Feature detection, feature inference і User Agent String — це способи визначення існування певної функції веб-технології в браузері.
- Feature detection — це спосіб визначити, чи існує функція у певних браузерах.
- Feature inference — припущення: якщо одна функція є (або ні), відповідно інша теж буде (або ні).
- User Agent String — це текстовий рядок, який надсилає кожен браузер і до якого можна отримати доступ через navigator.userAgent. Цей рядок містить у собі інформацію про виконавче оточення.
Докладніше тут:
14) Що таке підняття (hoisting) у JavaScript?
Переглянути відповідь
Під час компіляції коду, оголошення деяких змінних і функцій піднімаються вище за інший код у межах своєї області видимості. Цей процес і називається hoisting. Завдяки ньому функція буде успішно викликана, незважаючи на те, що в коді її виклик може йти перед оголошенням.
Докладніше тут:
15) Що таке спливання та занурення подій, у чому різниця між ними?
Переглянути відповідь
Сплив і занурення - це фази життєвого циклу події. Різниця полягає у моменті визначення факту настання події. Спочатку, при взаємодії користувача з елементом інтерфейсу (клік на кнопку, наприклад) подія занурюється від об'єкта window до цільового елементу (target), потім настає стадія спливання і подія спливає від target назад до window. Так, одна й та сама подія може бути перехоплена раніше чи пізніше.
Докладніше тут:
16) Які плюси та мінуси розширення вбудованих об'єктів JavaScript?
Переглянути відповідь
Плюсом цього підходу є розширення базового функціоналу об'єкта. Прийом може бути застосований для визначення поліфілів. Загалом, розширення поведінки вбудованих об'єктів не вітається і є поганою практикою (Monkey patching). Це порушує принцип інкапсуляції та засмічує базові об'єкти не задокументованою функціональністю.
Докладніше тут:
17) Опишіть різницю між == і === в JS?
Переглянути відповідь
Обидва оператори порівняння перевіряють тотожність. Відмінність полягає в тому, що подвійне дорівнює при порівнянні значень неявно наводить (перетворює) типи значень до єдиного, так рядок "1" і цифра 1 за такого порівняння тотожні. Потрійне дорівнює не виконує жодних неявних трансформацій, а отже вихідні типи матимуть значення. Таким чином рядок не буде дорівнювати числу і не важливо, що в обох операндах фігурує одиниця.
Докладніше тут:
18) Опишіть політику крос-доменних обмежень (same-origin policy) в контексті JS?
Переглянути відповідь
Same-origin policy (політика однакового джерела) - визначає як сайт (документ/скрипт), завантажений з одного джерела, може взаємодіяти в браузері з ресурсом (файлом, скриптом, об'єктом), з іншого джерела.
Приклад:
Якщо скрипт нашого сайту робить простий запит (GET) до чужого сервера та отримує у відповідь файл, при цьому у відповіді відсутня заголовок Access-Control-Allow-Origin або у значенні цього заголовка відсутній наш домен, браузер заборонить доступ до цього файлу (не дасть переглянути вміст відповіді) зі скриптів нашого сайту.
Докладніше тут:
19) Що таке Тернарний оператор, що говорить слово “тернарний” ?
Переглянути відповідь
Тернарний оператор - це умовний оператор, що має форму запису: <умова>? <істинний вираз> : <хибний вираз>. Тернарним його називають тому, що він має три операнди.
Докладніше тут:
20) Що таке strict режим у JS? У чому його переваги/недоліки?
Переглянути відповідь
Strict (суворий режим)— особливий режим роботи компілятора, що включає нові можливості і деякі поліпшення обумовлені стандартом ECMAScript 5, при якому змінюється поведінка деяких функцій. Включається директивою 'use strict'. Більшість сучасних браузерів підтримують strict режим, однак не все це робиться повністю. Суворий режим змінює семантику, що призводить до похибок та помилок. Потрібно підходити дуже уважно до використання строго режиму та проводити тести для перевірки працездатності коду як у браузерах, які підтримують строгий режим, так і тих, що не підтримують.
Докладніше тут:
21) Які основні переваги / недоліки написання коду мовою, що компілюється в JavaScript?
Переглянути відповідь
TypeScript - одна з мов, яка дозволяє писати код, що компілюється в JS.
Серед його переваг варто зазначити:
- Підтримка популярними IDE: Sublime Text, Visual Studio Code, WebStorm, Eclipse.
- Реалізує багато принципів об'єктно-орієнтованого програмування: модифікатори доступу, наслідування, інкапсуляцію та поліморфізм.
- Дозволяє швидше та простіше писати складні рішення, які легше тестувати та розвивати завдяки підтримці ООП та суворій типізації.
- Існує система для роботи з модулями, класами. Навіть є можливість створювати абстрактні класи.
- TypeScript зворотньо-сумісний із JavaScript. Будь-який код, написаний на JS буде виконано. Також можна писати змішаний код і він буде валідним.
Недоліки:
- Наявність додаткових файлів (*.ts, *.d.ts, *.map), що є незручним для невеликих проектів.
- Для деяких браузерів потрібне додаткове налаштування консолі для відладки TypeScript.
- TypeScript - мова з неявною статичною типізацією: тип може бути описаний як any, що відключить приведення до цього типу змінної. d.ts декларації не завжди відповідають поточній версії бібліотеки.
У цілому нині — TypeScript найкращий вибір для великих проектів, оскільки написання займає більше часу через описи декларацій класів і методів. Без статичної типізації в JavaScript, TypeScript — чудове рішення.
Докладніше тут:
22) У чому різниця між mutable та immutable об'єктами? Наведіть приклад immutable об'єкта в JS.
Переглянути відповідь
Immutable об'єкт - незмінний. Об'єкт, стан якого не може бути змінено після створення. Відповідно, mutable об'єкт може бути змінений після створення. Усі примітиви (числа, рядки, булеві значення тощо) є імутабельними.
Докладніше тут:
23) Які переваги та недоліки незмінності (immutability) ви можете виділити?
Переглянути відповідь
Переваги immutability:
- Просте та швидке відстеження змін (наприклад, не потрібно окремо порівнювати значення кожного поля вкладеного об'єкта. Можна просто порівняти посилання на об'єкти та відсіяти вкладені гілки порівнянь).
- Більш безпечне використання та тестування.
Недоліки:
- Створення нового об'єкта за кожної зміни може стати русурсо-витратною операцією.
Докладніше тут:
24) Як ви можете досягти незмінності (immutability) у власному коді?
Переглянути відповідь
Використання методу Object.freeze() запобігає зміні об'єкта: додавання, видалення або зміна властивостей. Використання ключового слова const замість var або let не робить константу незмінною, проте запобігає повторному присвоюванню нового значення.
Докладніше тут:
25) Опишіть різницю між синхронними та асинхронними функціями.
Переглянути відповідь
Синхронні функції - виконуються в порядку, в якому вони написані в тексті програми, по черзі.
Асинхронні функції - виконуються відкладено, потрапляючи перед виконанням у чергу, що дозволяє виконати їх, не блокуючи основний потік.
Докладніше тут:
26) Що таке цикл подій (event loop) в JS? Яка різниця між «стеком викликів» (call stack) та «чергою завдань» (task queue)?
Переглянути відповідь
Task queue - черга із завершених асинхронних завдань, готових до синхронної обробки. З цієї черги завдання будуть поступово переміщені в call stack.
Сall stack - стек викликів, за яким можна визначити, в якому місці програми зараз йде її обробка. Якщо стек не порожній, значить триває виконання синхронних завдань, а саме, функції, яка знаходиться на верхівці стека.
Event loop — механізм, що переміщає готові до синхронної обробки асинхронні завдання з task queue в call stack.
Докладніше тут:
27) У чому полягають різниця між змінними, створеними з допомогою let, var чи const?
Переглянути відповідь
- const — змінним оголошеним цим оператором має бути одразу надано значення. Надалі значення не може бути перевизначено. Змінна оголошена в такий спосіб не буде доступна за межами блочної області видимості.
- let — значення змінної, оголошеної цим оператором, може бути встановлене пізніше, а також може бути перевизначено в майбутньому. Змінна оголошена в такий спосіб не буде доступна за межами блочної області видимості. Не доступний hoisting. Не підтримує повторне оголошення.
- var — значення змінної, оголошеної цим оператором, може бути встановлене пізніше, а так само може бути перевизначене в майбутньому. Змінна оголошена у такий спосіб доступна за межами блочної області видимості. Доступний hoisting. Підтримує повторне оголошення.
Докладніше тут:
28) У чому різниця між класом ES6 і конструктором функцій ES5?
Переглянути відповідь
- Методи класу є неперелічуваними властивостями;
- Код усередині класу за замовчуванням обробляється у строгому режимі;
- Є розбіжності у синтаксисі;
Докладніше тут:
29) Чи можете ви назвати випадок у якому найбільш доречне застосування стрілочної функції? Чим цей тип функцій відрізняється від інших?
Переглянути відповідь
Стрілочні функції оголошуються особливою комбінацією символів () => {}. Мабуть, найбільш доречним варіантом застосування стрілочної функції є застосування її як callback функції. Це пояснюється основною відмінністю її від інших типів функцій - контекст виконання стрілочних функцій визначається не в момент виклику, а в момент оголошення (лексичний this).
Докладніше тут:
30) Що таке функція вищого порядку?
Переглянути відповідь
Функція вищого порядку - функція яка приймає як аргумент іншу функцію або повертає функцію, тобто працює з іншими функціями.
Array.prototype.reduce, Array.prototype.map та Array.prototype.filter – це функції вищого порядку.
Докладніше тут:
31) Наведіть приклад деструктуруючого присвоєння (destructuring assignment) об'єкта чи масиву
Переглянути відповідь
Destructuring assignment - механізм вилучення даних з масивів та об'єктів. При цьому використовуються літерали масиву або об'єкта (залежно від того, що деструктуруємо), що збільшує читабельність і дозволяє відразу сказати об'єкт якого типу деструктурується. Наприклад:
var [firstItem] = arr;
По квадратних дужках одразу видно, що arr - Це масив
Докладніше тут:
32) Наведіть приклад генерації рядка за допомогою шаблонного рядка ES6.
Переглянути відповідь
Шаблонний рядок - рядковий літерал, що дозволяє використовувати вирази всередині рядка. Оголошується косими лапками.
const variable = 'World!'
console.log(`Hello ${variable}`);
Докладніше тут:
33) Що таке каррування в JS?
Переглянути відповідь
Каррування (currying) - перетворення функцій з безліччю аргументів на набір вкладених функцій з одним аргументом. Після виклику такої функції з передачею їй аргументу, вона повертає нову функцію, яка чекає на наступний аргумент і так до отримання результату.
Докладніше тут:
34) Які переваги використання spread syntax і чим він відрізняється від rest syntax?
Переглянути відповідь
Spread — оператор, що складається з трьох точок. Перевага – у короткій формі запису. Відмінність — залежно від місця застосування цей оператор сприймається як spread чи rest оператор. Rest використовується для деструктуризації колекцій (поділ на окремі елементи), а spread, навпаки, для з'єднання окремих значень масиву.
let arr = ['one', 'two', 'three', 'four'];
// destructuring with three dots (rest)
let [first, second, ...rest] = arr;
console.log(first); // 'one'
console.log(second); // 'two'
console.log(rest); // ['three', 'four']
// concatenation with three dots. Same syntax but different behaviour
const restored = [first, second, ...rest];
console.log(restored) //['one', 'two', 'three', 'four'];
Докладніше тут: