Вопрос:
Какие типы данных существуют в JavaScript?
Ответ:
примитивные: number, bigint, string, boolean, null, undefined, symbol
object
Вопрос:
В чем смысл оборачивания всего содержимого JavaScript-файла в функцию?
Ответ:
Этот шаблон называется IIFE - Immediately Invoked Function Expression (немедленно вызываемое функциональное выражение). Этот подход позволяет:
обеспечить коду собственный блок видимости, то-есть контекст выполнения
избежать загрязнения глобальной области видимости глобальными переменными
избежать неумышленного переопределения уже существующих переменных в глобальной области видимости
Вопрос:
Что такое замыкание в JavaScript? Приведите пример.
Ответ:
Замыкание в JavaScript - это комбинация функции и лексического окружения, в котором она была определена.
Это позволяет ей обращаться к переменным и функциям этого лексического окружения в дальнейшем.
В следующем примере мы определяем функцию makeCounter(), которая фактически является фабричной функцией.
При вызове она возвращает дочернюю функцию, которая имеет доступ к лексическому окружению внешней функции, то-есть функции makeCounter().
Таким образом, возвращаемая функция запоминает переменную counter и в последующем изменяет ее значение.
function makeCounter(initial = 0) {
let counter = initial;
return function() {
return counter += 1;
}
}
const counterA = makeCounter(0);
console.log(counterA()); // 1
console.log(counterA()); // 2
const counterB = makeCounter(100);
console.log(counterB()); // 101
console.log(counterB()); // 102
Вопрос:
Как можно клонировать объект?
Ответ:
Можно использовать оператор rest ... пример [...newObj, oldObj]
Можно использовать Object.assign(newObj, oldObj).
Но эти подходы не позволяют выполнить глубокое клонирование.
Поэтому, если нам нужно клонировать объект со вложенными объектами, мы можем использовать либо метод какой-либо библиотеки (привет, lodash), либо сделать это средствами встроенного объекта JSON.
Вопрос:
В чем разница между undefined и is not defined?
Ответ:
undefined - это значение, присваемое объявленной, но не проинициализированной переменной.
Мы получаем undefined, обращаясь к существующей переменной. А в случае обращения к несуществующей (необъявленной) переменной, мы получим ошибку is not defined.
Вопрос:
Что такое hoisting (поднятие) в JavaScript?
Ответ:
Поднятие - это поведение компилятора JavaScript, заключающееся в поднятии объявлений переменных и функций в начало области видимости.
Благодаря поднятию мы можем использовать функции и переменные до их объявления в коде.
Однако, следовать учитывать, что поднимаются только объявления, но не присваивания значений.
По этой причине, например, мы можем использовать до объявления функцию, объявленную через Function Declaration, но не можем ту, которая объявлена через Function Expression.
Function Declaration — поднимается целиком (можно вызывать до объявления)
sayHello(); // "Привет!"
function sayHello() {
console.log("Привет!");
}
Function Expression — объявление переменной поднимается, присвоение — нет
myFn(); // TypeError: myFn is not a function
var myFn = function() {
console.log("Я функция-выражение");
};
Вопрос:
Что такое this?
Ответ:
this указывает на объект области видимости во время выполнения. По умолчанию this указывает на глобальный объект.
В браузере выражение this === window будет истинно.
Вопрос:
Как работает прототипное наследование?
Ответ:
Если отвечать кратко, в JavaScript все является объектами. Эти объекты связаны цепочками прототипов, по которым им передаются методы и свойства.
При обращении к свойству или методу объекта сначала происходит поиск этого свойства у самого объекта.
В случае неудачи поиск перенаправляется в его прототип, затем в прототип прототипа и так далее, пока искомое свойство не будет найдено, либо пока не закончится цепочка прототипов.
Вопрос:
Объясните, почему запись function foo(){}() вызывает ошибку и не работает, как IIFE?
Ответ:
Здесь дело в том, что круглые скобки вызова функции добавлены сразу после Function Declaration.
Однако, они могут следовать только за выражением (expression).
Поэтому мы должны либо прибегнуть к варианту с Function Expression, либо обернуть Function Declaration в скобки, тем самым превратив его в выражение.
const foo = function(){}()
// либо
(function foo(){})()
// либо со стрелочной функцией
(() => {})()
Вопрос:
В чем разница между null, undefined и undeclared?
Ответ:
null - это в прямом смысле "ничего". Можно использовать это значение в качестве плейсхолдера.
undefined - это значение для случая "объявлено, но не инициализировано".
undeclared - это ошибка, возникающая в случае обращении к необъявленной переменной.
Вопрос:
В каких случаях используются анонимные функции?
Ответ:
Анонимные функции чаще всего используются в качестве функций обратных вызовов. Также, каждая стрелочная функция является анонимной.
Вопрос:
Объясните разницу между const person = Person() и const person = new Person() при function Person(){}
Ответ:
Если функция Person() не возвращает явным образом создаваемый экземпляр, то вариант const person = Person() присвоит константе person значение undefined, поскольку именно таков результат void функции.
Если функция Person явным образом возвращает экземпляр, он станет значением константы person при const person = Person().
Однако, вариант с использование оператора new "выигрывает", поскольку он устанавливает корректную связь объекта person с цепочкой прототипов Person, в то время как выражение const person = Person() просто присваивает константе результат вызова функции.
Вопрос:
В чем разница между Function.prototype.call и Function.prototype.apply?
Ответ:
Оба метода вызывают исходный метод с подмененным контекстом, но .call принимает параметры через запятую, а .apply - массивом.
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = { name: 'Анна' };
greet.call(person, 'Привет', '!');
greet.apply(person, ['Привет', '!']);
Вопрос:
Как работает Function.prototype.bind?
Ответ:
Не вызывает функцию сразу, а создает новую функцию с "привязанным" контекстом
function greet(greeting, punctuation) {
return `${greeting}, ${this.name}${punctuation}`;
}
const person = { name: 'Анна' };
const boundGreet = greet.bind(person);
boundGreet('Привет', '!');
Вопрос:
Какие преимущества у использования Promise API вместо обратных вызовов?
Ответ:
Избавление от множества колбэков.
Один catch() для всей цепочки вместо проверки ошибок на каждом шаге
Promise.all(), Promise.race() для работы с несколькими асинхронными операциями
Вопрос:
Как отменить промис?
Ответ:
Встроенные промисы не отменяемы, но можно сделать так
- AbortController (современный подход)
const controller = new AbortController();
fetch('/api/data', { signal: controller.signal })
.then(response => response.json())
.catch(err => {
if (err.name === 'AbortError') {
console.log('Запрос отменен');
}
});
controller.abort();
- Кастомные отменяемые промисы
function cancellablePromise() {
let cancel;
const promise = new Promise((resolve, reject) => {
cancel = () => reject(new Error('Cancelled'));
setTimeout(() => resolve('Готово'), 5000);
});
return { promise, cancel };
}
const { promise, cancel } = cancellablePromise();
cancel();
Вопрос:
Объясните разницу между изменяемыми и неизменяемыми значениями
Ответ:
Значения примитивных типов (например, строка или число) не могут быть изменены после того, как попали в память.
Значения объектных типов (объекты, массивы) могут изменяться в ходе работы программы.
Вопрос:
Объясните разницу между синхронными и асинхронными функциями
Ответ:
JavaScript - это однопоточный язык, то-есть функции выполняются в синхронном порядке.
Приложение блокируется на время выполнения каждой конкретной функции. Так происходит по той причине, что JavaScript имеет только один стек вызовов.
С другой стороны, есть асинхронный способ выполнения функций, когда мы не блокируем весь интерфейс благодаря тому, что не дожидаемся выполнения функции, а подписываемся на событие с передачей обратного вызова.
Ну, или мы можем иметь дело с обещанием или с прочими внешними API вроде setTimeout.
В таком случае браузер помещает обработчик события в очередь задач, а когда наступает время его вызвать, он перемещает его в стек вызовов.
Вопрос:
Что такое цикл событий? В чем разница между стеком вызовов и очередью задач?
Ответ:
Стек вызовов - место, где JavaScript отслеживает, какие функции выполняются в данный момент (первым вошел, последним вышел).
Очередь задач - место, где ждут своей очереди колбэки от завершенных асинхронных операций (первым вошел, первым вышел).
Цикл событий - механизм, который проверяет: если стек пуст, то берет первую задачу из очереди и помещает в стек.
Вопрос:
В чем разница между let, const и var?
Ответ:
Область видимости (scope)
var - функциональная область видимости
let/const - блочная область видимости
function example() {
if (true) {
var x = 1;
let y = 2;
const z = 3;
}
console.log(x); // 1 (доступна)
console.log(y); // ReferenceError
console.log(z); // ReferenceError
}
Hoisting (поднятие)
var - поднимается и инициализируется как undefined
let/const - поднимаются, но недоступны до объявления
console.log(x); // undefined
console.log(y); // ReferenceError
console.log(z); // ReferenceError
var x = 1;
let y = 2;
const z = 3;
Переназначение
var - можно переназначать
let - можно переназначать
const - нельзя переназначать
var x = 1; x = 2; // ✅
let y = 1; y = 2; // ✅
const z = 1; z = 2; // ❌ TypeError
Повторное объявление
var - можно объявлять повторно
let/const - нельзя в той же области видимости
var x = 1;
var x = 2; // ✅
let y = 1;
let y = 2; // ❌ SyntaxError
Вопрос:
В чем разница между ES6 class и ES5 function constructor?
Ответ:
Классы, добавленные в стандарте EcmaScript 6, всего лишь синтаксический сахар поверх всем известных прототипов.
В работе эти подходы отличаются уровнем абстракции, который ожидаемо выше у классов - разработчику не приходится напрямую работать с прототипами.
Вопрос:
Что такое функция высшего порядка?
Ответ:
Функция, принимающая функцию обратного вызова в качестве аргумента.
Вопрос:
Что такое DOM?
Ответ:
DOM - Document Object Model (объектная модель документа). Другими словами, это дерево всех узлов страницы, которые распознал браузер в процессе обработки HTML-разметки.
DOM - это интерфейс, позволяющий JavaScript-коду взаимодействовать с шаблоном.
Вопрос:
В чем разница между областью видимости функции и блочной областью видимости?
Ответ:
И то, и то является полноценной областью видимости. Различие наблюдается при использовании ключевого слова var, которое ограничивается только областью видимости функции, но не блочной областью видимости.
Вопрос:
Разница между prototype и proto?
Ответ:
И то, и то является полноценной областью видимости. Различие наблюдается при использовании ключевого слова var, которое ограничивается только областью видимости функции, но не блочной областью видимости.
Ссылки
https://www.youtube.com/watch?v=zDlg64fsQow