От автора: самые стрессовые для меня вещи в разработке программного обеспечения это: собеседование по кодированию и дотошный менеджер или товарищ по команде. Не JavaScript, не this, не CSS, не Internet Explorer, а именно эти две вещи.
Если вы претендуете на должность старшего разработчика, который использует JavaScript, есть высокий шанс того, что вам зададут во время собеседования хитрые вопросы. Я знаю, что это несправедливо. Некоторые люди подводят тебя к грани, чтобы увидеть, из чего ты сделан. Это неприятный опыт.
Что вы можете сделать? Следуйте совету: «Практика позволяет нам совершенствоваться». Тратя достаточное количество времени, а лучше регулярно, на глубокое понимание JavaScript, вы улучшите свои навыки кодирования и, как положительный побочный эффект, навыки интервьюирования.
В этом посте вы найдете 7 на первый взгляд простых вопросов на собеседовании по JavaScript в 2019 году, которые таят в себе подвох. Их важно вспомнить не только Junior.
Хотя поначалу вопросы могут показаться случайными, они пытаются подключиться к важным концепциям JavaScript. Так что лучше потренируйтесь перед следующим собеседованием!
1. Случайная глобальная переменная
Вопрос. Для чего предназначены typeof a и typeof b в следующем фрагменте:
1 2 3 4 5 6 7 8 9 |
function foo() { let a = b = 0; a++; return a; } foo(); typeof a; // => ??? typeof b; // => ??? |
Ответ. Давайте внимательнее посмотрим на строку 2: let a = b = 0. Этот оператор на самом деле объявляет локальную переменную a. Тем не менее, он объявляет глобальную переменную b.
Ни в области видимости foo(), ни в глобальной области видимости нет объявленной переменной b. Так что JavaScript интерпретирует выражение b = 0 как window.b = 0.
b — это случайно созданная глобальная переменная
В браузере приведенный выше фрагмент кода эквивалентен:
1 2 3 4 5 6 7 8 |
function foo() { let a; window.b = 0; a = window.b; a++; return a; } foo(); typeof a; // => 'undefined' typeof window.b; // => 'number' |
typeof a равно ‘undefined’. Переменная a объявляется только в области видимости foo() и недоступна во внешней области видимости. typeof b оценивается, как ‘number’. b является глобальной переменной со значением 0.
2. Свойство длины массива
Вопрос. Каково значение clothes[0]:
1 2 3 4 |
const clothes = ['jacket', 't-shirt']; clothes.length = 0; clothes[0]; // => ??? |
Ответ. Свойство length объекта массива имеет особое поведение: Уменьшение значения свойства length имеет побочный эффект от удаления собственных элементов массива, индекс массива которых находится между старым и новым значениями длины.
Из-за этого поведения length при выполнении JavaScript clothes.length = 0 все элементы массива clothes удаляются.
clothes[0] равно undefined, потому что массив clothes был очищен.
3. Тест на внимательность
Вопрос. Каково содержимое массива numbers:
1 2 3 4 5 6 7 |
const length = 4; const numbers = []; for (var i = 0; i < length; i++);{ numbers.push(i + 1); } numbers; // => ??? |
Ответ. Давайте внимательнее посмотрим на точку с запятой ;, которая указана прямо перед открывающей фигурной скобкой {:
Эту точку с запятой легко пропустить, а она создает пустое выражение. Пустой оператор — это пустой оператор, который ничего не делает.
for() выполняет 4 раза нулевой оператор (который ничего не делает), не обращая внимания на блок, который на самом деле вводит элементы в массив: { numbers.push(i + 1); }. Приведенный выше код эквивалентен следующему:
1 2 3 4 5 6 7 8 9 10 11 12 |
const length = 4; const numbers = []; var i; for (i = 0; i < length; i++) { // does nothing } { // a simple block numbers.push(i + 1); } numbers; // => [5] |
for() увеличивает переменную i до 4. Затем JavaScript один раз входит в блок { numbers.push(i + 1); }, вводя 4 + 1 в numbers массив. Таким образом, numbers равно [5].
Моя история за этим вопросом
Давным-давно, когда я проходил собеседование на свою первую работу, мне задавали этот вопрос. На собеседовании мне дали 20 вопросов по кодированию, на которые я должен был ответить в течение 1 часа. Вопрос с нулевым оператором был в списке.
Решая задачу в спешке, я не увидел ; прямо перед фигурной скобкой {. Поэтому я ответил неправильно [1, 2, 3, 4].
Я был немного разочарован из-за таких нечестных уловок. Я спросил интервьюера, в чем причина подобных уловок?
Интервьюер ответил: «Потому что нам нужны люди, которые уделяют внимание деталям».
К счастью, я не попал на работу в эту компанию. Выводы делайте для себя сами.
4. Автоматическая вставка точки с запятой
Вопрос. Какое значение возвращает arrayFromValue()?
1 2 3 4 5 6 |
function arrayFromValue(item) { return [item]; } arrayFromValue(10); // => ??? |
Ответ. Легко пропустить новую строку между ключевым словом return и выражением [item]. Новая строка заставляет JavaScript автоматически вставлять точку с запятой между return и [item]. Вот эквивалентный код с точкой с запятой, вставленной после return:
1 2 3 4 5 |
function arrayFromValue(item) { return; [item]; } arrayFromValue(10); // => undefined |
return; внутри функции заставляет ее вернуть undefined. Поэтому arrayFromValue(10) оценивает, как undefined.
5. Классический вопрос: хитрое замыкание
Вопрос. Что выведет в консоль следующий скрипт:
1 2 3 4 5 6 |
let i; for (i = 0; i < 3; i++) { const log = () => { console.log(i); } setTimeout(log, 100); } |
Ответ. Если вы не слышали об этом сложном вопросе прежде, скорее всего, ваш ответ будет 0, 1 и 2, что неверно. Когда я впервые попытался решить эту задачу, это был и мой ответ! Есть два этапа выполнения этого фрагмента.
Фаза 1
for() выполняется 3 раза. Во время каждой итерации создается новая функция log(), которая захватывает переменную i. Затем setTimout() планирует выполнение log().
Когда цикл for() завершается, переменная i имеет значение 3.
log() является замыканием, которое захватывает переменную i, которая определена во внешней области видимости цикла for(). Важно понимать, что замыкание захватывает переменную лексически i.
Фаза 2
Второй этап происходит через 100 мс:
3 запланированных обратных вызова log() вызывают setTimeout(). log() считывает текущее значение переменной i, которая равна 3 и выводят на консоль 3.
Вот почему вывод в консоли 3, 3 и 3. Вы знаете, как исправить этот фрагмент кода, чтобы вывод был 0, 1 и 3? Пожалуйста, напишите свое решение в комментарии ниже!
6. Вычисления с плавающей точкой
Вопрос. Каков результат проверки на равенство?
1 |
0.1 + 0.2 === 0.3 // => ??? |
Ответ. Во-первых, давайте посмотрим на значение 0.1 + 0.2:
1 |
0.1 + 0.2; // => 0.30000000000000004 |
Сумма чисел 0.1 и 0.2 не совсем точно равна 0.3, но чуть больше 0.3. Из-за того, как числа с плавающей запятой кодируются в двоичном формате, такие операции, как сложение чисел с плавающей запятой, подвержены ошибкам округления.
Проще говоря, сравнение их напрямую не является точным. Таким образом, 0.1 + 0.2 === 0.3 равно false.
На 0.30000000000000004.com вы можете получить дополнительную информацию.
7. Подъем
Вопрос. Что произойдет, если вы получите доступ myVar и myConst до их объявления?
1 2 3 |
myVar; // => ???myConst; // => ??? var myVar = 'value'; const myConst = 3.14; |
Ответ. Подъем и временная мертвая зона — это две важные концепции, которые влияют на жизненный цикл переменных JavaScript.
Доступ к myVar до объявления оценивается как undefined. Поднятая var переменная до ее инициализации имеет значение undefined.
Однако, доступ к myConst до строки объявления выдает ReferenceError. Переменные находятся во временной мертвой зоне до строки объявления const myConst = 3.14.
8. Выводы
Вы можете подумать, что некоторые вопросы бесполезны для интервью. У меня такое же чувство, особенно в отношении теста на внимательность. Тем не менее, их могут задать.
В любом случае, большинство из этих вопросов действительно могут помочь оценить ваш опыт в JavaScript. Если у вас возникли трудности с ответом во время чтения поста, это показатель того, что вам нужно продолжать изучение! Справедливо ли задавать сложные вопросы во время интервью? Дайте мне знать о своем мнении.
Автор: Dmitri Pavlutin
Источник: //dmitripavlutin.com
Редакция: Команда webformyself.