“И есть еще белые, белые дни, белые горы и белый лед.
Но все, что мне нужно - это несколько слов и место для шага вперед.”(Виктор Цой)
Введение
Это вторая часть статьи, где будут вопросы, которые мне задавали и ответы на них. Я не берусь оценивать полезность вопросов и их смысл. Просто пишу все как есть, надо признать, что часть из них меня здорово обескуражили и мне пришлось уходить не солоно хлебавши, вспоминая один забавный анекдот:
"- Ну как на собеседование сходил? Успешно? - Да. Ручку у них спер" (ссылка)
Часть вопросов будет по typescript, часть по javascript, что-то будет из html, Node.js, настройки, библиотеки, концепции. В общем всё то, о чем говорят на собеседованиях.
Вопросы
Вопрос 1 (typescript):
Дан массив:
let a = [{a:1},{b:2},{c:3,d:4}];
Как создать объект конкатенацию всех элементов в массиве?
Ответ:
let c = {};
Object.assign(c,...a);
console.log(c);
Вопрос 2 (typescript):
interface IEvent {}
interface ISimpleEvent extends IEvent {}
interface IComplexEvent extends IEvent {}
class T implements ISimpleEvent {}
class D implements IComplexEvent {}
function processEvent(event: IEvent) {
if(event instanceof IComplexEvent) {
// do something complex }
else {
// do something simple
}
}
Как сделать так, чтобы этот код заработал?
Ответ:
interface IEvent {}
interface ISimpleEvent extends IEvent {}
interface IComplexEvent extends IEvent {}
class T implements ISimpleEvent {}
class D implements IComplexEvent {}
function isComplexEvent(event: IEvent): event is IComplexEvent {
return event instanceof D;
}
function processEvent(event: IEvent) {
if(isComplexEvent(event)) {
console.log("IComplexEvent");
} else {
console.log("ISimpleEvent");
}
}
let e: D = new D();
processEvent(e);
Вопрос 3 (typescript):
interface A {
prop1: {
a: number;
b: string;
}
}
function someFunc(k: typeOf A.prop1): void {}
Как заставить этот код работать?
Ответ:
interface A {
prop1: {
a: number;
b: string;
}
}
type sw = A["prop1"];
function someFunc(a: sw) {
console.log(a.b)
}
let q = {
prop1: {
a: 5,
b: "dddd"
}
}
someFunc(q.prop1);
Вопрос 4 (javascript):
Напишите функцию, которая вернет:
console.log(counter()); // output: 0
console.log(counter()); // output: 1
console.log(counter()); // output: 2
Ответ:
function getCounter() {
let count = 0;
return function() {
return count++;
}
}
let counter = getCounter();
console.log(counter()); // output: 0
console.log(counter()); // output: 1
console.log(counter()); // output: 2
Вопрос 5 (javascript):
Что возвращает функция match?
Ответ:
Объект Array, содержащий результаты сопоставления, или null, если ничего не было сопоставлено.
Вопрос 6:
Emit, on, once в Node.js
Ответ:
Это функции из модуля events, который позволяют работать с событиями. То есть мы вызываем некоторое событие и все подписанные на него слушатели реагируют на него соответствующим образом.
emit – вызывает событие.
on - Добавить listener в конце массива listeners для определенных событий. Этот метод не проверяет был ли listener добавлен когда-либо, или нет.
once - Добавить listener в массив listeners определенного массива. Но этот listener вызывается только 1 раз при происхождении события. Потом он удаляется из массива.
Вопрос 7 (javascript):
Как будет работать этот код?
console.log('Hi');
var to = setTimeout(function() {
console.log('callback');
}, 0);
//clearTimeout(to);
console.log('Bye');
Ответ:
Hi
Bye
callback
Если же раскомментировать //clearTimeout(to), то
Hi
Bye
Функция внутри setTimeout будет вызвана в момент, когда стек вызовов будет пуст, т.е. сразу после последнего действия в данном коде. setTimeout задерживает выполнение функции на указанное в параметре время плюс то время которое понадобиться на то чтобы выполнить все функции в стеке плюс функции в Callback Queue, которые там уже были на момент вызова SetTimeout().
Вопрос 8 (html):
box-sizing: border-box
Ответ:
значения width и height включают в себя размеры padding и border, но не включают margin.
Вопрос 9:
Сlean architecture
Ответ:
Модная ныне концепция разработки Web приложений. Советую почитать книгу Clean Architecture: A Craftsman's Guide to Software Structure and Design (Robert C. Martin Series). По большей части этим вопросом проверяют действительно ли вы участвовали в разработке крупных проектов на Сlean architecture или нет. В целом если в вашем проекте есть папки:
entities
use_cases
interfaces_adapters
external_interfaces
И вы понимаете, что в какой папке лежит, то сможете ответить на этот вопрос. Более подробно тут, так же можно посмотреть тут.
Вопрос 10:
Circuit breaker
Ответ:
Circuit breaker - это шаблон проектирования, который используют для работы со сбоями в системе. Он работает как прокси-сервис между приложением и удаленным сервисом. Если удаленный сервис начинает возвращать ошибку, то он либо перестеает отправлять на него запросы с нашего приложения, либо отправляет только часть из них. Позволяя сервису восстановиться. После восстановления сервися запросы от нашего приложения снова поступают на удаленный сервис (ссылка). У него есть 3 состояния:
Open
Closed
Half-Open
Тут можно почитать о нем более подробно, с картинками.
Вопрос 11:
Webpack
Ответ:
Webpack - это сборщик модулей. Он анализирует модули приложения, создает граф зависимостей, затем собирает модули в правильном порядке в один или более бандл (bundle), на который может ссылаться файл "index.html" (ссылка). Так же советую посмотреть Скринкаст по Webpack.
Вопрос 12:
Babel
Ответ:
Утилита, которая преобразует код написанный на ECMAScript 2015+ в обратно совместимую версию JavaScript, которая может выполняться старыми движками JavaScript (ссылка).
Вопрос 13:
SvelteJS
Ответ:
Новый перспективный компилятор с открытм кодом для разработки front end приложений. Он гораздо проще чем Angular, React и VueJS. Почитать про него можно тут или тут. Не знаю зачем у меня о нем спросили, возможно, проверяли мой кругозор. Я не писал на SvelteJS, но пишу на Angular, React и VueJS. После этих 3-х монстров хочется попробовать что-то более простое, но пока что на них довольно высокий спрос и приходиться работать с ними.
Вопрос 14:
npm ci
Ответ:
ci - это Continuous Integration. Аналог npm install, но в отличие от него берет зависимости из package-lock.json. Работает быстрее, но каждый раз удаляет node_modules. Для полной установки продукта по готовому package-lock.json имеет смысл использовать. Подробнее можно прочитать тут, тут или тут
Вопрос 15:
Cтрелочные функции и их отличие от обычных функций
Ответ:
Стрелочные функции - это функции типа:
(arg1, arg2, ...argN) => expression
или
(arg1, arg2, ...argN) => {
expression;
};
Отличия от обычных функций:
Не создает собственный контекст исполнения, всегда использует внешний. Значение this является значением окружающего контекста.
Оператор new не работает со стрелочной функцией
Неявный return для варианта: let func = (arg1, arg2, ...argN) => expression
Ключевое слово yield не может быть использовано в теле стрелочной функции
Не имеет собственного объекта arguments
Вопрос 16:
Continuous Integration
Ответ:
Непрерывная интеграция (Continuous Integration) — практика разработки программного обеспечения, которая заключается в постоянном слиянии рабочих копий в общую основную ветвь разработки и выполнении частых автоматизированных сборок проекта для скорейшего выявления потенциальных дефектов и решения интеграционных проблем (ссылка)
Заключение
Не факт, что у вас спросят то же самое, но в целом общее представление о том, что спрашивают и как отвечать я описал. Признаюсь, были и совсем неожиданные ситуации. Как-то раз я пришел на собеседование на frontend developer и отвечал исключительно на вопросы по SQL. В другом случае мы общались исключительно по Java. Так же был случай, когда я должен был на собеседовании настроить фреймворк для написания unit тестов. В общем, собеседование - это так весело, иногда руки потом пол дня дрожат. Особенно когда готовишься к одной теме, а спрашивать начинают совсем другую.
P.S.: Ответы даны краткие, не развернутые. Для полного понимания принципов работы советую прочитать часть первую (ссылка), а так же источники, которые я указал в данной статье.
Комментарии (19)
Alexandroppolus
21.02.2022 17:07+5Вопрос 2 (typescript):
Дурацкое решение, которое не будет работать на прочих реализациях IComplexEvent.
class D1 implements IComplexEvent {} processEvent(new D1());
хотя и сам вопрос тоже дурацкий
snobit
22.02.2022 09:28+2Отличный вопрос. Автор написал, что хотели услышать именно про Type Guards. Если это действительно так, для меня был бы звоночек о проф пригодности собеседущего и компании.
alexhovansky
21.02.2022 17:33+2Было бы здорово не показывать ответы на вопросы изначально, вроде тут есть
wert_lex
21.02.2022 19:46Ну, на Вопрос 2 есть сильно более лучший ответ. Есть более правильные, надёжные и масштабируемые способы решить эту проблему даже в масштабах технического интервью.
Branded/Tagged types
// Tagged types directly interface IEvent {} interface ISimpleEvent extends IEvent { __tag: 'ISimpleEvent'; } interface IComplexEvent extends IEvent { __tag: 'IComplexEvent'; } class T implements ISimpleEvent { __tag: 'ISimpleEvent' = 'ISimpleEvent'; } class D implements IComplexEvent { __tag: 'IComplexEvent' = 'IComplexEvent'; } function isComplexEvent(smth: any): smth is IComplexEvent { return smth?.__tag === 'IComplexEvent'; } function processEvent(event: IEvent) { if(isComplexEvent(event)) { console.log('ComplexEvent'); } else { console.log('SimpleEvent'); } } // Or Branded type helper type Branded<A, B> = A & { __brand: B }; type IEvent2 = Branded<{}, 'IEevent2'>; type ISimpleEvent2 = Branded<{/*...*/}, 'ISimpleEvent2'>; type IComplexEvent2 = Branded<{/*...*/}, 'IComplexEvent2'>; // ... and so on
Alexandroppolus
21.02.2022 20:02+2Да тоже так себе, особенно функция isComplexEvent. Постановка вопроса сама по себе неправильная. Не надо проверять, что там за интерфейс. В интерфейсе IEvent просто должен быть метод process. Либо, на самый крайний случай, поле type.
Вот, например - https://refactoring.guru/ru/design-patterns/composite. Названия интерфейсов прямо сходу напомнили этот паттерн.
DanUnited
22.02.2022 08:54+1Это решение JS, которое непосредственно мутирует и влияет на исходный объект. Тебе необходимо иметь поле и желательно на стороне backend и на стороне frontend и в БД чтобы так было.
А представленное решение это функционал TypeScript через Guards
wert_lex
22.02.2022 12:59Так а по другому не получится, если действительно очень хочется опираться на интерфейсы - никаких интерфейсов в рантайме нету. А для того, чтобы TypeGuards завелись для интерфейсов - эти самые интерфейсы нужно в рантайме как-то различать. И различать их путём перебора всех возможных наследников - ну такая себе идея.
Там выше заметили, что вообще вопрос неправильный и спрашивать надо не так :). Ну, вопрос такой, какой есть. И Type Labeling вполне себе стандартный подход для решения этой проблемы в TS. Да, типы придётся потэгать ручками. Но, компилятор любезно даст по рукам, если забыть это сделать, а на этом все проблемы и заканчиваются
AndyPike
22.02.2022 00:10console.log(counter()); // output: 0
console.log(counter()); // output: 1
console.log(counter()); // output: 2
За решение создавать глобальную переменную через var внутри функции - голову бы оторвал в 2022 году. Сейчас тут только yield в самый раз.alex_29 Автор
22.02.2022 00:23Спасибо за var, изменил на let. Это замыкание (closure), довольно распространенное решение в js. https://ru.stackoverflow.com/questions/694664/Создать-счетчик-через-замыкание
victor-homyakov
22.02.2022 05:32+1npm ci
Аналог npm install ... Работает гораздо быстрее
Очень спорное утверждение. Важное отличие команды `npm ci` - сначала она полностью удаляет папку `node_modules`. Для большого проекта на небыстром накопителе это может занять очень много времени. Последующее копирование в `node_modules` гигабайтов пакетов тоже может занять заметное время.
hackteck
22.02.2022 08:28Для getCounter() лучше всего подошли бы генераторы
https://developer.mozilla.org/ru/docs/Web/JavaScript/Guide/Iterators_and_Generators#генераторы
Psychosynthesis
23.02.2022 02:50+5Забавно что каждый раз когда кто-то приводит решения каких-либо задач на TS в каментах появляется кто-нибудь, кто называет предложенное решение плохим, предлагает свой вариант, затем находится уже очередной знаток TS, который находит проблему в новом решении и... судя по некоторым постам так может продолжаться достаточно долго.
И при этом все продолжают думать что TS - классный язык.
RealPeha
Некоторые ответы крайне сомнительные