Чем примитивы отличаются от объектов?
|
Примитивы — |
Что значит "передача по значению" в JavaScript?
|
При вызове функции параметр получает копию значения аргумента. Для примитива копируется сам примитив, для объекта — значение ссылки на объект. Переназначение параметра не меняет внешнюю переменную. |
Передаются ли объекты по ссылке в JavaScript?
|
Точнее говорить: объекты тоже передаются по значению, но этим значением является ссылка на объект. Функция и вызывающий код получают две копии ссылки на один объект. Поэтому мутация объекта видна снаружи, а переназначение параметра — нет. |
Чем отличается ссылка на объект от самого объекта?
|
Объект содержит состояние в памяти, а ссылка позволяет найти конкретный объект. Несколько переменных могут содержать ссылки на один объект. Изменение через любую из них будет наблюдаться через остальные. |
Почему изменение свойства объекта внутри функции видно снаружи?
|
Скопированная ссылка параметра указывает на тот же объект, что и внешняя переменная. Запись свойства меняет этот общий объект. Новый объект при этом не создается. |
Почему переназначение параметра внутри функции не меняет внешнюю переменную?
|
Параметр — локальная переменная функции. Присваивание заменяет только локальную копию ссылки, а внешняя переменная продолжает указывать на прежний объект. function changeUser(user) {
user.name = 'Alex';
}
function replaceUser(user) {
user = {name: 'Bob'};
}
const user = {name: 'Max'};
changeUser(user);
console.log(user.name); // Alex
replaceUser(user);
console.log(user.name); // Alex |
Как работает сравнение объектов через ===?
|
|
Что такое shallow copy и deep copy?
|
Shallow copy создает новый верхний объект, но вложенные объекты остаются общими. Deep copy рекурсивно создает независимые вложенные значения. Полное копирование может быть дорогим и не всегда имеет смысл для immutable updates. |
Чем отличаются spread, Object.assign и structuredClone?
|
Spread и |
Какие ограничения есть у JSON.parse(JSON.stringify(...)) для deep copy?
|
Метод теряет |
Какие типы данных есть в JavaScript?
|
В JavaScript есть семь примитивных типов: Все остальные значения относятся к типу // Примитивные
string; // "hello"
number; // 123, 3.14, NaN, Infinity
bigint; // 123n
boolean; // true / false
undefined; // значение не задано
null; // пустое значение
symbol; // уникальный идентификатор
// Ссылочный тип
object; // {}, [], function, Date, Map, Set и т.д.Важно: typeof null; // "object" — старая странность JS
typeof []; // "object"
typeof function () {}; // "function"typeof Symbol('id'); // "symbol" |
В чем разница между call и apply, bind в JS?
|
call и apply делают одно и то же: вызывают функцию с явно заданным this. call Аргументы передаются через запятую: function greet(city, age) {
console.log(`${this.name}, ${city}, ${age}`);
}
const user = {name: 'Max'};
greet.call(user, 'Moscow', 32);
// Max, Moscow, 32
// fn.call(thisArg, arg1, arg2, arg3);function greet(city, age) {
console.log(`${this.name}, ${city}, ${age}`);
}
const user = {name: 'Max'};
greet.apply(user, ['Moscow', 32]);
// Max, Moscow, 32bind тоже работает с this, но не вызывает функцию сразу. Он создает новую функцию, у которой this уже заранее привязан. function greet(city) {
console.log(`${this.name} from ${city}`);
}
const user = {name: 'Max'};call — вызывает сразу. apply — вызывает сразу, но аргументы массивом. bind — НЕ вызывает сразу const boundGreet = greet.bind(user);
boundGreet('Moscow');
// Max from Moscow |
Что такое область видимости в JS?
|
Область видимости в JavaScript — это правило, которое определяет, где переменная, функция или класс доступны в коде. function test() {
const name = 'Max';
console.log(name); // доступна
}
console.log(name); // ошибка: name не видна снаружиОсновные виды scope в JS
Доступно везде в файле/программе: const appName = 'My App';
function log() {
console.log(appName);
}
var виден внутри всей функции: function test() {
var x = 1;
if (true) {
var y = 2;
}
console.log(y); // 2
}
let и const видны только внутри блока {}: if (true) {
const x = 1;
let y = 2;
}
console.log(x); // ошибка
console.log(y); // ошибка
В ES-модулях переменные не попадают в global scope: const value = 123;
export {value}; |
В чем отличие нативных (Native) объектов от хост-объектов (Host objects)?
|
Нативные объекты — часть спецификации языка. Они доступны нам вне зависимости от того, на каком клиенте исполняется наш код. Примеры: Array, Date и Math. Полный список нативных объектов. var users = Array(); // Array — нативный объектВстроенные (Built-in): Array, Date, Math, String, Promise, Object. Пользовательские: Объекты, создаваемые вами через new Object(), литералы {} или классы. Контекстные: Объект globalThis (или window в браузере, global в Node.js), Math и JSON. Хост-объекты (Host objects) Это объекты, предоставляемые средой выполнения (окружением), в которой запущен JavaScript (браузер, сервер Node.js и т.д.). Они не являются частью самого языка, зависят от платформы и могут различаться. В браузере: window, document, location, history, XMLHTTPRequest, fetch, элементы DOM, localStorage. В Node.js: Объекты для работы с файловой системой (fs), процессами (process), операционной системой (os). |
Что такое Object.groupBy и когда его использовать?
|
const operations = [
{date: '2017-07-31', amount: 5422},
{date: '2018-03-31', amount: 5654},
{date: '2017-08-31', amount: 5451},
];
const byYear = Object.groupBy(operations, ({date}) => date.slice(0, 4));
// {
// "2017": [...],
// "2018": [...]
// }
|
Чем Object.groupBy отличается от Map.groupBy?
|
const active = {label: 'active'};
const archived = {label: 'archived'};
const users = [
{name: 'Max', status: active},
{name: 'Anna', status: archived},
{name: 'Kate', status: active},
];
const grouped = Map.groupBy(users, ({status}) => status);
grouped.get(active);
// [{ name: "Max", ... }, { name: "Kate", ... }]Выбор зависит от того, какие ключи нужны и будет ли результат дальше использоваться как объект или |
Что такое Object.fromEntries?
|
const entries = [
['name', 'Max'],
['role', 'frontend'],
];
const user = Object.fromEntries(entries);
// { name: "Max", role: "frontend" }Пример фильтрации свойств: const params = {
search: 'angular',
page: 1,
empty: undefined,
};
const cleaned = Object.fromEntries(Object.entries(params).filter(([, value]) => value !== undefined));
// { search: "angular", page: 1 } |
Что делает Object.hasOwn?
|
const user = Object.create({role: 'admin'}) as {
name?: string;
role: string;
};
user.name = 'Max';
Object.hasOwn(user, 'name'); // true
Object.hasOwn(user, 'role'); // false
'role' in user; // trueВ отличие от |
Чем Object.hasOwn отличается от оператора in?
|
|
Чем Object.entries отличается от Object.fromEntries?
|
const user = {name: 'Max', role: 'frontend'};
const entries = Object.entries(user);
const copy = Object.fromEntries(entries);Symbols не попадают в |
Что возвращает Object.keys и в каком порядке?
|
Integer-like ключи идут по возрастанию, остальные строковые ключи - в порядке добавления: const value = {10: 'ten', 2: 'two', name: 'Max'};
Object.keys(value); // ["2", "10", "name"]Порядок определен спецификацией, но бизнес-логику сортировки лучше выражать явно, а не связывать со способом хранения объекта. |
Что такое Array.prototype.reduce?
|
const total = [10, 20, 30].reduce((sum, value) => sum + value, 0);
// 60Initial value стоит задавать явно, особенно если массив может быть пустым: const byYear = operations.reduce<Record<string, typeof operations>>((groups, operation) => {
const year = operation.date.slice(0, 4);
groups[year] ??= [];
groups[year].push(operation);
return groups;
}, {});Не стоит использовать |
Чем flat отличается от flatMap?
|
const nested = [[1, 2], [3]];
nested.flat(); // [1, 2, 3]
const users = [
{name: 'Max', roles: ['admin', 'editor']},
{name: 'Anna', roles: ['viewer']},
];
const roles = users.flatMap(({roles}) => roles);
// ["admin", "editor", "viewer"] |
Когда использовать flatMap вместо map().flat()?
|
const values = [1, -1, 2];
const positive = values.flatMap((value) => (value > 0 ? [value] : []));
// [1, 2]
|
Чем toSorted отличается от sort?
|
const numbers = [10, 2, 30];
const sorted = numbers.toSorted((first, second) => first - second);
console.log(numbers); // [10, 2, 30]
console.log(sorted); // [2, 10, 30]
const numbers = [10, 2, 30];
numbers.sort((first, second) => first - second);
console.log(numbers); // [2, 10, 30]Для чисел нужен comparator, иначе значения сортируются как строки. |
Чем reverse отличается от toReversed?
|
const source = [1, 2, 3];
const reversed = source.toReversed();
console.log(source); // [1, 2, 3]
console.log(reversed); // [3, 2, 1] |
Чем splice отличается от toSpliced?
|
const source = ['a', 'b', 'c'];
const updated = source.toSpliced(1, 1, 'x');
console.log(source); // ["a", "b", "c"]
console.log(updated); // ["a", "x", "c"] |
Что делает array.with?
|
const source = ['draft', 'review', 'done'];
const updated = source.with(1, 'approved');
console.log(source); // ["draft", "review", "done"]
console.log(updated); // ["draft", "approved", "done"]Недопустимый индекс приводит к |
Почему immutable-методы массивов полезны в Angular?
|
readonly users = signal<ReadonlyArray<User>>([]);
sortByName(): void {
this.users.update((users) =>
users.toSorted((first, second) => first.name.localeCompare(second.name)),
);
}Мутация массива на месте может не создать ожидаемого реактивного обновления и усложняет сравнение предыдущего и нового состояния. |
Что такое sparse array?
|
Sparse array, разреженный массив, содержит пустые слоты, в которых нет свойства с соответствующим индексом. Это не то же
самое, что явное значение const sparse = [1, , 3];
0 in sparse; // true
1 in sparse; // false
sparse.length; // 3Методы ведут себя по-разному: |
Какие базовые API есть у Date?
|
const now = new Date();
now.getFullYear();
now.getMonth(); // 0-11
now.getDate(); // День месяца
Date.now(); // Текущий timestamp в миллисекундах
now.getTime(); // Timestamp конкретной даты
|
Что такое ISO-формат даты?
|
ISO 8601 - распространенный стандарт записи даты и времени. В JavaScript часто встречается формат
const iso = '2026-06-20T10:30:00.000Z';
|
Что делает Date.prototype.toISOString?
|
const date = new Date('2026-06-20T10:30:00+03:00');
date.toISOString();
// "2026-06-20T07:30:00.000Z"Метод удобен для API, логов, сериализации и приведения моментов времени к единому формату. |
Какие ошибки часто допускают при работе с Date?
const date = new Date();
date.setDate(date.getDate() + 1); // Мутирует исходный объектДля более сложной работы с датами развивается |
Как сравнивать даты в JavaScript?
|
Моменты времени удобно сравнивать по timestamp через const first = new Date('2026-06-20T10:00:00.000Z');
const second = new Date('2026-06-20T12:00:00.000Z');
first.getTime() < second.getTime(); // trueДля API моменты времени обычно передают в ISO/UTC. Если значение является календарной датой без времени, например днем
рождения, его часто безопаснее хранить отдельной строкой |
Чем Promise.all отличается от Promise.allSettled?
|
const results = await Promise.allSettled([loadProfile(), loadRecommendations()]);
const successful = results.filter((result): result is PromiseFulfilledResult<unknown> => result.status === 'fulfilled');
|
Что произойдет при ошибке внутри Promise.all?
|
Итоговый promise отклонится с причиной первого обнаруженного rejection. Остальные запущенные операции автоматически не отменяются и могут продолжить работу. Если допустим частичный результат, используют |
Когда использовать Promise.race?
|
Важно: проигравшие операции автоматически не отменяются. |
Чем Promise.any отличается от Promise.race?
|
|
Что такое Promise.withResolvers?
|
const {promise, resolve, reject} = Promise.withResolvers<string>();
button.addEventListener('click', () => resolve('confirmed'), {once: true});
const result = await promise;Метод удобен при адаптации callback/event API, но внешнее управление promise усложняет жизненный цикл. Для обычной
последовательной логики чаще проще |
Что такое Promise.try?
|
const result = await Promise.try(parseConfig, rawConfig);API удобно на границе, где callback может быть синхронным или асинхронным. Это новый стандартный метод, поэтому перед использованием нужно проверить поддержку целевых browsers и runtime. |
Что такое URL и URLSearchParams?
|
const url = new URL('/users', 'https://example.com');
url.searchParams.set('page', '2');
url.searchParams.set('search', 'Angular & RxJS');
url.toString();
// "https://example.com/users?page=2&search=Angular+%26+RxJS"Это безопаснее и понятнее ручной конкатенации query string. |
Как добавлять, изменять и удалять query parameters?
const params = new URLSearchParams('page=1');
params.set('page', '2');
params.append('tag', 'angular');
params.delete('page');
params.toString(); // "tag=angular"
|
Чем URLSearchParams.append отличается от set?
|
const params = new URLSearchParams();
params.append('tag', 'angular');
params.append('tag', 'rxjs');
params.get('tag'); // "angular"
params.getAll('tag'); // ["angular", "rxjs"]Для multi-value параметров используют |
Что такое AbortController и AbortSignal?
|
const controller = new AbortController();
const request = fetch('/api/users', {
signal: controller.signal,
});
controller.abort();
await request; // Rejection с AbortErrorОдин signal можно передать нескольким связанным операциям. |
Как сделать timeout для fetch?
|
Современный вариант использует const response = await fetch('/api/users', {
signal: AbortSignal.timeout(5_000),
});Если нужен ручной контроль, создают const controller = new AbortController();
const timeoutId = setTimeout(() => controller.abort(), 5_000);
try {
return await fetch('/api/users', {signal: controller.signal});
} finally {
clearTimeout(timeoutId);
} |
Чем отмена запроса отличается от игнорирования результата?
|
Игнорирование результата не останавливает сетевую работу и обработку ответа. Настоящая отмена через В Angular это встречается в autocomplete, навигации между страницами и уничтожении компонентов. |
Что такое REST?
|
REST (Representational State Transfer) — это набор правил и принципов для построения взаимодействия между программами (клиентом и сервером) через интернет. Обычно клиент (например, браузер или мобильное приложение) запрашивает данные у сервера, а тот их возвращает, чаще всего по протоколу HTTP. Ключевые принципы REST Клиент-серверная модель:
|
Что было до REST и после?
|
REST (Representational State Transfer) — это набор правил и принципов для построения взаимодействия между программами (клиентом и сервером) через интернет. Обычно клиент (например, браузер или мобильное приложение) запрашивает данные у сервера, а тот их возвращает, чаще всего по протоколу HTTP. Ключевые принципы REST Клиент-серверная модель:
Идея: клиент вызывает удаленную функцию как обычную функцию. userService.getUser(123);На уровне сети это превращалось в запрос к серверу. Минус: клиент часто сильно завязан на серверные методы. То есть API выглядит как набор команд.
SOAP — более формальный XML-based подход. <soap:Envelope>
<soap:Body>
<GetUser>
<UserId>123</UserId>
</GetUser>
</soap:Body>
</soap:Envelope>Особенности:
Минус: тяжеловесно, много boilerplate.
REST стал популярным как более простой HTTP-подход. call getUser(123)Появляется ресурс: GET / users / 123;Вместо: call deleteUser(123)REST-стиль: Главная идея REST: API строится вокруг ресурсов, а HTTP-методы описывают действие. REST никуда не исчез. Он до сих пор основной стандарт для обычных web API. Но рядом появились другие подходы.
Идея: клиент сам говорит, какие поля ему нужны. query {
user(id: 123) {
name
avatar
posts {
title
}
}
}Плюсы:
Минусы:
Хорошо подходит, когда UI сложный и REST начинает плодить много endpoint-ов.
Идея: быстрые типизированные контракты между сервисами. Обычно используется не browser ↔ backend, а backend ↔ backend. service UserService {
rpc GetUser (GetUserRequest) returns (User);
}Плюсы:
Минусы:
|
Чем отличается queueMicrotask от setTimeout?
console.log('1');
setTimeout(() => console.log('setTimeout'), 0);
queueMicrotask(() => console.log('queueMicrotask'));
console.log('2');Вывод: 1;
2;
queueMicrotask;
setTimeout; |
Что такое Event loop?
|
JavaScript в браузере выполняется в основном в одном потоке. Поэтому ему нужен диспетчер, который по очереди обрабатывает:
console.log('1');
setTimeout(() => {
console.log('2');
}, 0);
Promise.resolve().then(() => {
console.log('3');
});
queueMicrotask(() => {
console.log('4');
});
console.log('5');1;
5;
3;
4;
2; |
Как устроена память в JavaScript (memory heap, memory stack)?
|
Упрощенная модель состоит из call stack и heap:
Сборщик мусора освобождает объекты, которые больше недостижимы от корней приложения. Основная идея современных сборщиков мусора — mark and sweep. Типичные причины утечек: забытые подписки и обработчики, бесконечно растущий кеш, таймеры, замыкания и ссылки на
удаленные DOM-узлы. В Angular для подписок можно использовать |
Что такое this и расскажите про область видимости?
|
Область видимости определяет, где доступна переменная. В JavaScript есть глобальная, модульная, функциональная и блочная
область видимости.
class Counter {
count = 0;
increment = (): void => {
this.count += 1;
};
}Нельзя определять |
В чем отличие var от const, let?
const user = {name: 'Ann'};
user.name = 'Kate'; // ДопустимоПо умолчанию используют |
Как устроено прототипное наследование в JavaScript?
|
Каждый обычный объект может иметь внутреннюю ссылку const animal = {moves: true};
const dog = Object.create(animal);
dog.barks = true;
console.log(dog.moves); // Найдено в прототипеСинтаксис Слишком глубокие и изменяемые цепочки усложняют код. В прикладной разработке часто предпочитают композицию небольших объектов наследованию. |
Что такое Promise и для чего используется в JS?
|
fetch('/api/users')
.then((response) => response.json())
.catch((error: unknown) => handleError(error))
.finally(() => hideLoader());Обработчики Для параллельной работы есть |
Что такое call-stack, task-queue (приведите примеры работы)?
|
Call stack хранит активные вызовы функций. JavaScript выполняет верхний frame стека и снимает его после возврата из функции. Task queue содержит готовые к выполнению задачи: таймеры, DOM-события и другие callbacks. Event loop передает следующую задачу в стек, когда стек пуст и обработаны microtasks. console.log('A');
setTimeout(() => console.log('B'), 0);
Promise.resolve().then(() => console.log('C'));
console.log('D');Порядок вывода: |
Что такое макро и микро задачи в JS?
|
Термин task часто неформально называют macrotask.
После завершения текущей task движок полностью очищает очередь microtasks и только затем может выполнить рендер и перейти к следующей task. Если microtasks непрерывно добавляют новые microtasks, они могут задержать рендер и обработку событий. Поэтому тяжелую
работу нельзя бесконечно дробить только через Promise или |
Что такое класс и интерфейс?
|
Класс описывает создание объектов, их состояние и поведение. Класс существует во время выполнения JavaScript. Интерфейс TypeScript описывает контракт формы значения и используется только при проверке типов. После компиляции интерфейс исчезает. interface UserRepository {
findById(id: string): Promise<User | null>;
}
class HttpUserRepository implements UserRepository {
async findById(id: string): Promise<User | null> {
return loadUser(id);
}
}Интерфейс нельзя напрямую использовать как Angular DI-токен, потому что его нет в runtime. Для DI используют класс,
|
Что такое конструктор класса?
|
Конструктор — специальный метод, который выполняется при создании экземпляра через class User {
constructor(
readonly id: string,
readonly name: string,
) {}
}В производном классе до обращения к В Angular конструктор класса не является lifecycle hook. Для компонентов он должен оставаться простым: DI и базовая инициализация выполняются в конструкторе, а логика, зависящая от входных данных, размещается в соответствующем lifecycle hook или реактивной модели. |
