7 простых, но хитрых вопросов на интервью по JavaScript
Топ моих самых важных вещей в разработке программного обеспечения:
- Собеседования при поиске работы
- Токсичные менеджеры или товарищи по команде
Не JavaScript, не this, не CSS, и даже не Internet Explorer, а 2 пункта выше.
Если вы квалифицируетесь в качестве Senior Developer, который работает с JavaScript, есть хороший шанс что вам могут задать сложные вопросы во время собеседования.
Я знаю, что это несправедливо. Некоторые неизвестные люди ставят вас в тупик, чтобы увидеть, как вы будете реагировать и посмотреть из чего вы сделаны. Это неприятный опыт.
Что можно сделать в этой ситуации?
Следуйте совету: «Практика совершенствует». Тратя достаточное количество времени, а лучше регулярно, на глубокое понимание JavaScript, вы улучшите свое умение кодировать и, как положительный побочный эффект, улучшите навыки интервьюирования.
В этом посте вы найдете 7 на первый взгляд простых, но хитрых вопросов на JavaScript-интервью.
Хотя поначалу вопросы могут показаться случайными, но они базируются на важных концепциях JavaScript. Так что лучше потренируйтесь перед следующим собеседованием!
1. Случайные глобальные переменные
Вопрос
Чему равные значения typeof a и typeof b в следующем фрагменте:
function foo() { let a = b = 0; a++; return a; } foo(); typeof a; // => ???typeof b; // => ???
Ответ
Давайте подробнее рассмотрим строку 2: let a = b = 0. Это утверждение действительно объявляет локальную переменную a. Тем не менее, оно объявляет глобальную переменную b.
Но переменной b, нет ни в области видимости foo(), ни в глобальной области видимости. Таким образом, JavaScript интерпретирует выражение b = 0 как window.b = 0.
Таким образом b — случайно созданная глобальная переменная.
В браузере приведенный выше фрагмент кода эквивалентен:
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. Свойство length типа Array
Вопрос
Чему равно значение clothes[0]:
const clothes = ['jacket', 't-shirt']; clothes.length = 0; clothes[0]; // => ???
Ответ
Свойство length объекта массива имеет особое поведение:
Уменьшение значения свойства length имеет побочный эффект удаления собственных элементов массива, индекса массива которых находится между старым и новым значениями длины.
Из-за этого поведения length, когда JavaScript выполняет clothes.length = 0, все элементы массива clothes будут удалены.
Таким образом clothes[0] имеет значение undefined, потому что массив clothes был очищен.
3. Тест орлиный глаз
Вопрос
Что будет находится в переменной numbers:
const length = 4; const numbers = []; for (var i = 0; i < length; i++);{ numbers.push(i + 1); } numbers; // => ???
Ответ
Давайте внимательнее посмотрим на точку с запятой ; которая находиться прямо перед открывающей фигурной скобкой {:
Эту точку с запятой легко пропустить, хотя она создает нулевое выражение. Пустой оператор — это пустой оператор, который ничего не делает.
for() выполняет итерацию 4 раза с нулевым оператором (который ничего не делает), игнорируя блок, который фактически помещает элементы в массив: {numbers.push (i + 1); }.
Приведенный выше код эквивалентен следующему:
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()?
function arrayFromValue(item) { return [item]; } arrayFromValue(10); // => ???
Ответ
Легко пропустить новую строку между ключевым словом return и выражением [item].
Вот эквивалентный код с точкой с запятой, вставленной после return:
function arrayFromValue(item) { return; [item]; } arrayFromValue(10); // => undefined
return; внутри функции возвращает значение undefined.
Таким образом, arrayFromValue(10) возвращает undefined.
5. Классический вопрос: хитрое замыкание
Вопрос
Что выведет на консоль следующий скрипт:
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(). Важно понимать, что замыкание захватывает переменную лексически.
Фаза 2
Второй этап происходит через 100 мс:
- 3 запланированных обратных вызова log() вызываются методом setTimeout(). log() читает текущее значение переменной i, которое равно 3, и выводит его в консоль.
Вот почему на консоль выводятся 3, 3 и 3.
Знаете ли вы, как исправить этот фрагмент что бы в консоль выводилось 0, 1 и 2? Пожалуйста, напишите свое решение в комментарии ниже!
6. Математика с плавающей точкой
Вопрос
Каков результат проверки на равенство?
0.1 + 0.2 === 0.3 // => ???
Ответ
Во-первых, давайте посмотрим на значение 0,1 + 0,2:
0.1 + 0.2; // => 0.30000000000000004
Сумма чисел 0,1 и 0,2 не совсем 0,3, она чуть выше 0,3.
Из-за того, как числа с плавающей запятой кодируются в двоичном формате, такие операции, как добавление чисел с плавающей запятой, подвержены ошибкам округления.
Проще говоря, сравнение floats напрямую не является точным.
Таким образом 0,1 + 0,2 === 0,3 равно false.
Посмотрите 0.30000000000000004.com если хотите об этом почитать подробнее.
7. Hoisting (Поднятие)
Вопрос
Что произойдет, если вы получите доступ к myVar и myConst до объявления?
myVar; // => ???myConst; // => ??? var myVar = 'value'; const myConst = 3.14;
Ответ
Подъем и временная мертвая зона (dead zone) — это две важные концепции, которые влияют на жизненный цикл переменных JavaScript.
Переменная myVar, до ее инициализации, имеет значение undefined.
Однако доступ к myConst до строки объявления приводит к возникновению ошибки ReferenceError. Переменные const находятся во временной мертвой зоне, до строки объявления const myConst = 3.14.
Почитайте руководство JavaScript Variables Hoisting in Details, чтобы получить больше деталей о подъеме.
Заключение
Вы можете подумать, что некоторые из рассмотренных вопросов бесполезны для интервью. У меня такое же чувство, особенно в отношении теста орлиного глаза. Но тем не менее, их могут спрашивать на интервью.
В любом случае, большинство из этих вопросов действительно могут быть полезны, если вы опытный программист. Если у вас возникли трудности с ответом на некоторые вопросы во время чтения поста, это хороший показатель того, что вы должны изучить дальше!
Справедливо ли задавать сложные вопросы во время интервью? Дайте мне знать ваше мнение. (в блоге автора статьи)
Оригинальная статья: Dmitri Pavlutin — 7 Simple but Tricky JavaScript Interview Questions
«Знаете ли вы, как исправить этот фрагмент что бы в консоль выводилось 0, 1 и 3?»
Наверно имелось в виду «0, 1, и 2»?
Да вы правы, так и есть (хотя в оригинальной статье 0,1 и 3)
for (let i = 0; i {
console.log(i);
}
setTimeout(log, 100);
}
// 0, 1, 2
В комментариях обрезается код 🙁
Да, они не предназначены для кода. Можно оставить комментарий в блоге автора оригинальной статьи: https://dmitripavlutin.com/simple-but-tricky-javascript-interview-questions/
Я мидл. не ответил орлинный глаз. Никогда не встречал такой ошибки в коде где либо. Ещё нет инф в каком режиме работаем. Но судя по всему это не строгий, иначе так легко глоб перем не создать было бы
const log = (t) => () => {
console.log(t);
}
setTimeout(log(i), 100);
точнее так=))
for (var i = 0; i {
const log = () => {
console.log(i);
}
setTimeout(log, 100);
})(i);
}
for ( let i = 0; i < 3; i++ ) setTimeout( () => console.log(i), 1000 )
Пропущена ; перед (function(j){…})(i)
А можно просто внести объявление i через let в цикл, тоже проканает
for (let i =0 ; i < 3; i++) setTimeout ( () => console.log( i ), 100) // 0, 1, 2