Стандартные вопросы и задачи на собеседовании для junior программистов

  1. Ключевые особенности JavaScript?

Во-первых, JavaScript является интерпретируемым языком. Это означает, что код не нужно компилировать перед выполнением; браузеры могут выполнять JavaScript прямо во время загрузки веб-страницы. Это упрощает процесс разработки и тестирования.

Во-вторых, JavaScript является языком с поддержкой событий, что позволяет разработчикам устанавливать слушатели событий для различных действий пользователя, таких как клики мышью или ввод текста. Это делает возможным создание интерактивных пользовательских интерфейсов.

Кроме того, JavaScript поддерживает объектно-ориентированное программирование (ООП). Разработчики могут создавать объекты, которые могут содержать данные и функции, что способствует организации и повторному использованию кода. Также можно создавать классы, и на основе них создавать схожие объекты Это облегчает работу с большими проектами.

Однако важно понимать, что механизм, используемый JavaScript для реализации ООП, отличается от классического подхода, который применяется в таких языках, как Java или C#. В JavaScript используется прототипное наследование, где объекты могут наследовать свойства и методы от других объектов. Это означает, что каждый объект может иметь другой объект в качестве своего “прототипа”. Таким образом, все в JavaScript является объектами, включая функции и даже сами классы, которые по сути являются синтаксическим сахаром поверх прототипного наследования.

Другой важной особенностью является асинхронность. JavaScript использует такие механизмы, как промисы и async/await, которые упрощают работу с асинхронными операциям, такими как запросы к удалённым серверам. Это позволяет загружать данные и выполнять другие задачи, не блокируя пользовательский интерфейс.

JavaScript также динамически типизирован, и это означает, что переменные могут изменять свои типы во время выполнения. Т.е. переменная может сперва содержать, например, число, а затем во время выполнения программы, этой переменной можно присвоить любое значение другого типа. Например, строку.

Еще одна особенность — это работа с DOM (Document Object Model), т.е. объектная модель документа – по сути это древовидная структура вашего сайта которая состоит из связанных между собой узлов. Узлы в DOM – это теги, тексты внутри тегов и атрибуты.

С помощью DOM JavaScript позволяет изменять содержимое, структуру и стиль HTML-документа, что делает возможным создание динамических и адаптивных пользовательских интерфейсов.

И наконец, JavaScript поддерживает большое количество библиотек и фреймворков (например, React, Angular, Vue), которые существенно ускоряют процесс разработки и делают его более удобным. Эти библиотеки и фреймворки мы не проходили в этом курсе, так как – это отдельная тема заслуживающая отдельных курсов. Поэтому я бы советовал перед устройством на работу освоить какой-нибудь популярную библиотеку или фреймворк, например React. Так как по реакту больше всего вопросов на собеседовании. Там на самом деле нет ничего сложного, все сложное мы уже прошли.

Переходим к следующему вопросу.

2. Что такое DOM и как с ним работать в JS?

Ну отчасти мы уже на него ответили в первом вопросе, но здесь можно добавить про узлы. Что узлы делятся на на 6 типов:

Элементы (Element Node) – это просто html теги как div, img и т.д.

Текстовые узлы (Text Node) – это текст, который содержится внутри элементов, т.е. тегов

Атрибуты (Attribute Node) – Это уже знакомые вам атрибуты тегов, такие как class, id и т.д.

Комментарии (Comment Nodes) – Html комментарии тоже являются отдельными узлами

Документ (Document Nodes) – Документ является верхним уровнем узла в DOM. Он представляет собой всю веб-страницу.

Документный фрагмент (Document Fragment Nodes) – данный узел, является аналогом узла Документа, но не является частью основного дерева DOM. Т.е. он не отображается на вашей веб-странице. Данный узел нужен, когда вы создаете теги, и вам необходимо, чтобы они где то хранились, но пока не отображались в документе. Для того хранилища и подходит узел Документальный фрагмент. Также такие теги можно просто хранить в оперативной памяти (когда мы в практиках создаем новые теги с помощью метода createElement, то они автоматически хранятся в оперативной памяти), но хранение таких тегов в Документном фрагменте считается более эффективным, особенно когда необходимо обрабатывать большое количество узлов, так как обработка тегов в документном фрагменте происходит быстрее, чем в оперативной памяти.

Но в этом курсе я не оказывал как хранить теги в документальном фрагменте. Давайте это исправим.

 Итак продолжаем. Все узлы организованны в древовидную структуры и подразделяются на:

  1. Родительский узел: это узел который содержит другие узлы. Например этот тег боди является родителем для всех этих узлов.
  2. Дочерние узлы – узлы, которые находятся внутри родительского узла. Например этот тег див является дочерним для тега body
  3. Соседние узлы – узлы, которые находятся на одном уровне в дереве и имеют общего родителя. Например, эти теги div section являются соседними узлами. Если тег содержит атрибут , текст внутри то узел элемента, узел атрибута и текста находятся на одном уровне.

Третий вопрос. Как можно манипулировать классами элементов с помощью JS?

Для начала нам надо получить доступ к необходимому элемент например с помощью метода querySelector объекта document. Далее на этом элементе обратимся в свойству classList который вернет объект DOMTokenList, который в свою очередь предоставит нам следующие методы:

Также добавить класс мы можем с помощью метода setAttribute. Но с ним надо быть осторожней, так как если у элемента уже есть класс, то он его заменит. Чтобы с помощью setAtribute добавить класс, можно написать так.

4. Что такое callback — функция и как она работает?

Callback-функция в JavaScript — это функция, которая передаётся в другую функцию в качестве аргумента. И часто еще говорят в определение, что колбек функция вызывается после завершения выполнения вызывающей её функции. Но это справделиво только отчасти. Если колбек функция вызывается синхронно, как например в этом примере:

Т.е. в этом примере перед колбеком идет инструкция консоль лог с текстом HI. И эта инструкция выполнится только когда завершится callBack.

Но благодаря таким функциям как setTimeout или setInterval колбек превращается в асинхронную функцию и уже выполнится после вызывающей его функции. Например напишем такой пример.

И как вы видите, несмотря на то что после колбека идет инструкция консоль лог, и мы еще поставили во времени ожидания 0, колбек все равно выполнился после завершения вызывающей её функции.

Двигаемся дальше. Следующий 5 вопрос: Как создать элемент и добавить его в DOM?

Здесь все просто, создать новый элемент мы можем с помощью метода createElement. А добавить этот элемент в DOM мы можем с помощью метода appendChild, а также с помощью метода InsertBefore, которым мы не пользовались в этом курсе.

Метод appendChild используется для добавления нового узла (элемента) как последнего дочернего элемента к указанному родительскому элементу. Это означает, что когда вы используете appendChild, вы всегда добавляете элемент в конец списка дочерних узлов родительского элемента. Например, если у вас есть родительский элемент с несколькими детьми, использование appendChild добавит новый узел после всех уже существующих дочерних узлов.

С другой стороны, insertBefore позволяет вам вставлять новый узел перед определенным существующим дочерним элементом. Это дает вам возможность более точно контролировать, где именно вы хотите разместить новый узел.

Переходим к следующему вопросу. Что такое async и await, и как они упрощают работу с асинхронным кодом?

async и await — это ключевые слова, которые значительно упрощают написание и чтение асинхронного кода. Как вы уже знаете Асинхронные операции позволяют выполнять действия, не блокируя основной поток выполнения, что особенно важно для задач, таких как запросы к серверу или работа с файловой системой. В JavaScript до введения async и await использовались такие конструкции, как колбеки (callback) и промисы (Promises), но их использование порой приводило к сложному и нечитабельному коду, особенно при последовательном выполнении нескольких асинхронных операций. Как помните, например в промисах мы создавали объект промис, внутри обязательно создавали функции resolve и reject, а если мы в методе then хотели вернуть новый промис, то нам надо было после слова return создавать новый промис.

А при помощи асинк и эвейт мы пишем гораздо меньше кода и поэтому он становится гораздо легко читаемым. Кстати, в уроке где мы изучали ключевые слова async и await, чтобы обработать ошибку мы ее сперва создали с помощью ключевого слова throw, а потом выводили ошибку на экран с помощью метода catch. Но мы можем также воспользоваться конструкцией try catch.

Конструкция try...catch в языке JavaScript используется для обработки ошибок, которые могут возникать во время выполнения кода. Это позволяет разработчику создать более надежные программы, которые могут реагировать на ошибки, не прерываясь.

Когда вы помещаете блок кода в конструкцию try, JavaScript будет отслеживать любые ошибки, возникающие внутри этого блока. Если ошибка возникает, управление передается в блок catch, где вы можете указать, как именно вы хотите обработать эту ошибку.

Как видите, сперва сам браузер написал что мы неправильно написали веб адрес, а затем отработал нам код внутри конструкции кэч.

Переходим к вопросу номер 8. Какие современные библиотеки и фреймворки вы знаете и для чего они используются?

Как я уже говорил, изучение фреймфорков и библиотек должна стать вашей следующей задачей, после прохождения этого курса. Начните с React.

Что такое JSON и как с ним работать в JS?

JSON (JavaScript Object Notation) — это текстовый формат, используемый для обмена данными, основанный на синтаксисе объектов JavaScript. Он стал стандартом для передачи данных между клиентом и сервером из-за своей простоты и читаемости. JSON позволяет представлять структуры данных в виде пар “ключ-значение”, что облегчает их использование и манипуляцию.

В JavaScript существует несколько методов для работы с JSON, так как он идеально интегрирован в язык. Основные методы, которые применяются для работы с JSON, — это JSON.stringify() и JSON.parse().

Чтобы преобразовать JavaScript-объект или массив в строку JSON, используется метод JSON.stringify(). А чтобы преобразовать строку JSON обратно в JavaScript-объект, используется метод JSON.parse()

И остался последний вопрос – Что такое модульность в JS и как ее можно достичь?

Этой темы в этом курсе не было, но давайте сейчас её быстро разберем. Модульность в JavaScript — это подход к разработке, который позволяет организовать код в отдельные, переиспользуемые и независимые модули, т.е. файлы. Есть два популярных типа модульности – это Moдули ES6 и CommonJS. Но нас интересует только Модули ES6, так как CommonJS используется для серверной среды Node.js.

Итак Модули ES6 — это встроенный механизм модульности в JavaScript. Он позволяет вам импортировать и экспортировать функции, объекты или примитивы между модулями. Это достигается с помощью ключевых слов import и export.

Для понимания давайте я покажу это на примере. Создам папку и внутри неё будут два файла. Первый стандартный index.html. Создам необходимые теги. А во втором файле будут необходимые функции для нашей работы. Допустим этот будут функции сложить и вычесть. Обязательно перед ключевым словом function пишем слово export. Тем самым мфы указываем что эта функция будет использоваться в другом файле.

Теперь мы можем в файле index.html импортировать эти функции. Но для начала в теге скрипт необходимо указать, что мы используем модули с помощью атрибута type. Далее чтобы импортировать сюда необходимые функции нам надо написать ключевое слово import.

Далее мы должны указать ссылку на модуль. Чтобы сказать браузеру, что наш модуль находится в той же папке, что и файл index html надо написать точку и косую черту и далее название файла. Теперь давайте используем например функцию add. Проверим.

Вы можете спросить, а чем модули отличаются от обычный файлов с js кодом. Ведь мы могли написать функции в обычном js файле и подключить их с помощью тега script и его атрибута source.

Во первых это область. Переменные и функции, определенные в модуле, находятся в своей собственной области видимости. Это означает, что они не конфликтуют с переменными и функциями, определенными в других модулях или в глобальной области видимости, что помогает избежать распространенных проблем с конфликтами имен.

Во вторых – это время загрузки. Загрузка: Модули загружаются асинхронно, что делает их более подходящими для современных веб-приложений. Это позволяет улучшить производительность и снизить время загрузки, так как модули могут загружаться по мере необходимости.

И последнее отличие – это Кэширование: Браузеры обычно кэшируют модули, что может улучшить скорость загрузки приложения при последующих посещениях. Это позволяет избежать повторной загрузки использовать уже загруженные модули.

И нам осталось разобрать две стандартные задачи которые задаются на собеседовании.

Первая задача – это написать функцию, которая вычисляет факториал числа. Факториал числа n определяется как произведение всех положительных целых чисел от 1 до n (n!). Т.е. если это 5, то функция должна умножить 1 на 2, затем получившееся значение на 3 и т.д. до 5.

Конечно есть много способов как это решить, например можно использовать цикл for внутри функции.

Но чаще данную функцию записывают так.

Второй самой часто задаваемой задачей является такая –

Напишите функцию, которая определяет, является ли переданное слово палиндромом. Палиндром — это слово, которое читается одинаково в обоих направлениях (как слева направо, так и справа налево). Например шалаш.