Разработчики JavaScript широко востребованы в it-индустрии. Так, при желании повысить, к примеру, свой оклад, недостатка в вариантах трудоустройства, как правило, не бывает. Однако, прежде чем устроиться на работу, необходимо на практике продемонстрировать свои знания и пройти собеседование. В этой стать будут рассмотрены 5 типичных вопросов, задаваемых кандидату при собеседовании, чтобы оценить его знания по JavaScript.
Вопрос 1-ый: Область видимости (scope)
Возьмем следующий код:
jQuery
(function() { var a = b = 5; })(); console.log(b);Что что покажет консоль?
Ответ
Код выше выведет 5 .
Подвох заключается в том, что IIFE (немедленно выполняемая функция) имеет два присваивания, но переменная a объявлена посредством ключевого слова var . То есть a - это локальная переменная функции, а b , напротив, присваивается глобальной области видимости/действия.
Одним подвохом вопрос не ограничивается: внутри функции (строгий режим) ("usestrict";) не применяется. В случае его применения код выдал бы ошибку "UncaughtReferenceError: bisnotdefined" . Надо помнить, что жесткий режим требует, чтобы вы явно ссылались на глобальную область видимости, если так было задумано. То есть вы должны написать следующее:
jQuery
(function() { "use strict"; var a = window.b = 5; })(); console.log(b);Вопрос 2-ой: Создайте «нативные» методы
Опишите функцию repeatify объекта String . Функция принимает целое число. Число определяет сколько раз необходимо дублировать строку. Функция возвращает повторяемую строку столько раз, сколько было заранее определено. Пример:
Console.log("hello".repeatify(3));
Будет выведено: hellohellohello .
Ответ
Возможное решение показано ниже:
Javascript
String.prototype.repeatify = String.prototype.repeatify || function(times) { var str = ""; for (var i = 0; i < times; i++) { str += this; } return str; };Вопрос проверяет знания разработчика о наследовании в JavaScript и о свойстве prototype , а также его знания касательно расширения функциональности нативных данных.
Еще одна цель – показать, что соискатель знает, как избежать замещения возможных заранее установленных функций. То есть перед тем как описать функцию нужно убедиться в том, что она не создана:
Javascript
String.prototype.repeatify = String.prototype.repeatify || function(times) {/* code here */};Этот прием особенно полезен, когда просят заклинить JavaScript функцию.
Вопрос 3-ий: Подъем (Hoisting)
Каким будет результат выполнения этого кода и почему?
Javascript
function test() { console.log(a); console.log(foo()); var a = 1; function foo() { return 2; } } test();Ответ
Результат будет – undefined и 2 .
Причина: переменная и функции (перемещены на верх функции), а назначенные переменным значения потеряны. То есть, когда переменная выводится в консоли, она существует в функции (объявлена), но еще undefined . Другими словами, код выше равнозначен следующему:
Javascript
function test() { var a; function foo() { return 2; } console.log(a); console.log(foo()); a = 1; } test();Вопрос 4-ый: как работает this в JavaScript
Каким будет результат следующего кода? Обоснуйте ответ.
Javascript
var fullname = "John Doe"; var obj = { fullname: "Colin Ihrig", prop: { fullname: "Aurelio De Rosa", getFullname: function() { return this.fullname; } } }; console.log(obj.prop.getFullname()); var test = obj.prop.getFullname; console.log(test());Ответ
Код выведет AurelioDeRosa и JohnDoe . Причина: контекст функции (то, на что ссылается ключевое слово this) в JavaScript зависит от того, как функция вызывается, а не определяется.
В первом console.log() , getFullname() вызывается как функция объекта obj.prop . Таким образом, контекст ссылается на последний объект и функция возвращает fullname свойство данного объекта. С другой стороны, когда переменной test присваивается getFullname() , контекст ссылается на глобальный объект (window). Это объясняется тем, что переменная test по умолчанию установлена как свойство глобального объекта. Именно по этой причине функция возвращает значение свойства fullname от window , которое в нашем случае определенно в первой строке сниппета.
Вопрос 5-ый: call() и apply()
Возвращаясь к 4 вопросу, сделайте так, чтобы последний console.log() выводил AurelioDeRosa .
Вопрос может быть решен путем переопределения контекста функции. Для этого можно использовать методы call() или apply() . Если вам неизвестны эти функции, советую обратиться к статье . В коде ниже используется метод call() , однако в нашем случае метод apply() даст тот же результат:
Javascript
console.log(test.call(obj.prop));Заключение
Были рассмотрены 5 типичных вопрос при собеседовании для проверки знаний разработчика JavaScript. От собеседования к собеседованию вопросы могут варьироваться в деталях и частностях, однако их общая проблематика остается неизменной.
Продолжаем разбирать часто задаваемые вопросы на интервью.
6. Что такое прототипное наследование (prototypal inheritance)
Грамотным ответом будет: изначально каждый объект обладает свойством — прототипом. Вы можете добавлять в него методы и свойства. Создавать другие объекты на основе прототипа. Создаваемый объект автоматически унаследует свойства и своего прототипа. Если свойство в новом объекте отсутствует, то будет произведен его поиск в прототипе.
Let car = function(model) {
this.model = model;
};
car.prototype.getModel = function(){
return this.model;
}
let honda = new car("honda");
console.log(honda.getModel()); //honda
let bmw = new car("bmw");
console.log(bmw.getModel()); //bmw
Функция car называется конструктором. Далее мы добавляем метод getModel в ее прототип, с помощью специальной конструкции car.prototype.getModel(). Если вы не поняли о чем здесь говорится, настоятельно рекомендую ознакомиться с прототипным ООП: https://learn.javascript.ru/prototypes
30% вам зададут этот или похожий вопрос.
7. Разница между объявлением функции (function declaration) и функциональным выражением (function expression)?
Function funcA(){ console.log("function declaration"); }; var funcB = function() { console.log("function expression"); }
Как видим, функциональное выражение, — это переменная, которой присваивается функция.
Важная особенность заключается в том, что функция объявленная через function declaration доступна по тексту программы до ее описания. В то время как функциональное выражение ведет себя как переменная, таким образом, к функции можно обратиться только после. Если мы в предыдущем примере, в самом начале допишем две строки:
Console.log(funcA()); //function declaration
concole.log(funcB()); //Uncaught ReferenceError: funcB is not defined.
Кстати, вместо var можно использовать let, со всеми вытекающими последствиями, касающимися области видимости.
Если вы хотите передать функцию в качестве аргумента другой функции, то вам необходимо воспользоваться функциональным выражением. Потому что это переменная. То есть передать переменную в другую функцию.
8. Что такое промисы (promises) и для чего их используют.
Ответить на данный вопрос иногда трудно, но вы можете просто сказать, что с помощью них можно выполнять действия (функции, методы) в асинхронном режиме. Добиться асинхронности можно и с помощью колбэков, но в случае большой вложенности (большого количества асинхронных действий), мы получим плохо читаемый код.
$.ajax({ url: "test.json", success: function(r) { $.ajax({ url: "baz.json?" + r.test, success: function(result) { $("#div1").html(result); } }); } });
Видите, насколько сильно ветвится данный код? Теперь, напишем тоже самое с использованием промисов (схематично):
Var p1 = new Promise(function(resolve, reject) { resolve($.ajax("test.json")); }); p1.then(function(r){ return new Promise(…); }).then(function(result){ $(“#div1”).html(result); });
9. Вопрос про setTimeout()
Скорее всего, у вас не будут спрашивать, что же это такое, поскольку ответ на подобный вопрос слишком очевиден. Вместо этого предложат фрагмент кода, и вы должны будете ответить, каков результат его выполнения.
Console.log("a"); console.log("b"); console.log("c"); //увидим последовательный вывод a затем b и с. Теперь сделаем тоже самое, только вывод "а" обернем в setTimeout().
SetTimeout(function() {
console.log("a");
}, 0);
По логике вещей, поскольку таймаут равен 0, мы можем предположить, что последовательность вывода останется такой же. Однако на самом деле, мы увидим сначала b, потом c и только в конце – a.
Так происходит потому, что когда мы использует setTimeout, код, который в него заключен, становится асинхронным. JS выполнит его после того, как освободится стэк. То есть после b и c.
10. Замыкания (closure) и как их использовать
Наверняка вам зададут вопрос на собеседовании.
Когда одна функция возвращает другую функцию (или объект), последняя содержит окружение своего как бы «родителя». Обратимся к примеру:
Let bar = function() {
let i = 0;
return {
setI(b) {
i = b;
},
getI() {
return i;
}
}
};
let x = bar();
x.setI(2);
console.log(x.getI()); //2
Напоследок, хотелось бы посоветовать не спешить с ответами при прохождении собеседования, особенно на вопросы, связанные с анализом предложенного кода. Часто очевидные на первый взгляд вопросы содержат хитрости и ловушки. Остановитесь, подумайте лишнюю минутку. Задайте уточняющие вопросы — это продемонстрирует вашу внимательность и ответственное отношение к делу. Поможет выявить интервьюверу ход ваших мыслей. Собственно, в основном для этого и задаются хитрые или сложные задачи. Гораздо важнее продемонстрировать правильное мышление, даже если ответ на вопрос в итоге будет неверным.
Человек не может знать всё, это в принципе невозможно. Часто бывает так, что на прошлой работе вы сталкивались с одними технологиями и приёмами, а на новой команда имеет другие взгляды на архитектуру и пользуется не очень знакомыми вам библиотеками. Вот почему грамотный интервьювер в первую очередь постарается выяснить, что за человек перед ним, как он мыслит, его аналитические способности. В конце концов, недостающие пробелы заполнить очень легко, чего нельзя сказать о правильном мышлении программиста, которое формируется только с опытом.
Неделя собеседований на Хабре прошла, но я решил добить ещё живого уважаемого читателя статьёй, в которой поделюсь некоторыми заданиями, которые мне давали на собеседованиях работодатели в течение последнего месяца (среди них - Яндекс, Topface, ITMozg, парочка весьма интересных и пара довольно мутных стартапов).
Разумеется, у вас не получится успешно пройти собеседование, просто заучив ответы на эти вопросы. Ответ на каждый вопрос будет необходимо пояснить, иногда - очень подробно. Многие вопросы будут ещё дополнены собеседующими. Я прошу рассматривать эти вопросы как некоторую «планку», которой необходимо самостоятельно достичь, чтобы стать Junior"ом в хорошей компании.
Собственно, сами задания
1
Представьте, что у нас есть квадратное поле-сетка, по которому ходит бродяга.
Напишите объект «Бродяга», содержащий его координаты и четыре метода, реализующих шаг бродяги вверх, вниз, вправо и влево.
Как реализовать в таком объекте цепочку вида:
Vagabond.goUp().goLeft().goDown().goDown().goRight();
2
Имеется массив произвольной длины, заполненный случайными значениями:
Var list = ;
необходимо найти значение максимального элемента.
3
Необходимо отправить на сервер набор данных без перезагрузки страницы. Перечислите способы сделать это, назовите самый кроссбраузерный.
4
В чем разница между уткой == и === ?
5
Что такое Local Storage, Cookies и Session Storage? В чем разница между ними?
6
@media only screen and (max-width: 1200px) {
}
Что это за конструкция? Зачем она может понадобиться?
7
Чем в Git отличаются merge и rebase ?
8
Var a = new F();
var b = new F();
alert(a == b);
function F() {}
Сделать так, чтобы a == b возвращало true .
9
Напишите результаты выполнения операций:
"1" + 2;
1 + "2";
null == undefined;
null == 0;
null > 0;
null >= 0;
"a" > "A";
10
Var list = ;
function sum() {
var sum = 0;
for (i=0; i
11
Представьте большую и сложную страницу, которая очень медленно загружается. Допустим, на ней плохо всё. Ваша задача - оптимизировать время загрузки. Ваши действия?
Заключение
Практически все задания нужно было выполнить устно или в старой доброй IDE «Paper & Pencil». Безбажного кода никто не требовал. Тех, что поадекватнее, в первую очередь, интересовал ход мысли, а не знание тонкостей технологии. Но, естественно, уровень знаний HTML, JS и CSS тоже имеет значение (а вы как хотели). Собеседования в некоторых случаях больше напоминают экзамен с хорошими преподавателями (так было в ITMozg и в Topface), в некоторых - приятную дружескую беседу с чаепитием (Яндекс, Radario), а в некоторых - вообще чёрт знает что (не буду называть компании, к тому же, они малоизвестны).
Если кому-нибудь из читателей после прочтения придёт в голову мысль «Оказывается, на собеседованиях даже в самые крутые компании бояться нечего. Работа в Яндексе и Топфэйсе - это вполне досягаемо», значит, я писал это не зря.
Спасибо за внимание. Всем удачи.
Доброго времени суток, дорогой гость! Рада приветствовать на страницах своего блога.
Сегодня речь пойдет о том, какие вопросы задаются на техническом собеседовании кандидату на позицию Javascript-разработчика. Цель — проверить необходимый уровень знаний языка кандидата и теоретической подготовки.
Мне бы хотелось выразить благодарность Senior Frontend Developer Греченок Евгению и Senior Backend Developer Гиззатову Марселю за помощь в создании статьи. Те вопросы, которые идут дальше, из их методички, которую они используют для собеседований кандидатов «и на 30 тысяч, и на 130». Большое спасибо, ребята, за время, которое мне уделили, и считаю, что для меня на собеседовании был хороший стимул убрать пробелы в собственных знаниях и сделать еще один шаг к тому, чтобы стать профессионалом.
Вопросы по JavaScript (синтаксис и особенности языка)
1. Если вам необходимо проверить, определено ли свойство у самого объекта … (hasOwnProperty)
2. Как работает this (http://bonsaiden.github.io/JavaScript-Garden/ru/#function.this)
3. Замыкания (http://bonsaiden.github.io/JavaScript-Garden/ru/#function.closures)
4. Определение переменных (всплытие)
5. Переменные let, const, var (https://learn.javascript.ru/let-const)
6. Равенство и сравнение (оператор == и ===)
7. Операторы typeof и instanceof (для чего используются http://bonsaiden.github.io/JavaScript-Garden/ru/#types.instanceof)
8. Почему нельзя использовать eval (http://bonsaiden.github.io/JavaScript-Garden/ru/#core.eval)
9. Деструктуризация (https://learn.javascript.ru/destructuring)
10. Строки-шаблоны (https://learn.javascript.ru/es-string)
11. Классы (прототипы, современные)
12. Итераторы (https://learn.javascript.ru/iterator)
13. Генераторы (https://learn.javascript.ru/generator)
14. Новые типы данных (https://learn.javascript.ru/set-map)
15. Что такое Eventloop? Объясните принцип его работы.
![](https://i0.wp.com/alexaweb.ru/wp-content/uploads/2017/08/codeguru.jpg)
Общие вопросы по программированию
- Отличие компилируемого языка от интерпретируемого
Чем компиляция С отличается от Java
- Отличие статической типизации от динамической
- Отличие наследование от композиции (https://habrahabr.ru/post/325478/)
- Алгоритмы и их сложность (JS https://tproger.ru/translations/algorithms-and-data-structures/)
a. В приложении к любому языку привести примеры стандартных методов сортировки / обхода дерева / поиска в массиве, дикте с пояснением о их сложности и как работают.
- FIFO, LIFO
- Структуры данных (JS https://learn.javascript.ru/data-structures)
a. Числа, Строки
b. Объекты (ассоциативные массивы), передача по ссылке (что передаётся по значению)
c. Массивы
d. Деревья, Списки (связанный, ссылочный)
- Архитектура (в чём разница)
a. асинхронная,
b. многопоточная
- Микросервисы
a. Будет ли микросервисами распределённая архитектура через общую шину данных
b. Требования к микросервисам
i. горизонтальное масштабирование
ii. отказоустойчивость
- Преимущества микросервисов:
i. легкая поддержка (небольшие сервисы легче)
ii. нет ограничения на языки и библиотеки для решения задачи
iii. упрощенное тестирование, возможность замокать взаимодействия
iv. легкое накатывание и откатывание новых версий
v. можно экспериментировать с технологиями
Гибкие методологии
- Зачем нужны
- Какие подходы есть
- Выявление проблем в разработке, зачем нужна ретроспектива в scrum
- Распределение задач по разработчикам
- горят сроки
- планирование
И напоследок...
Задача на понимание JavaScript
Задача 1. Что выведет данный код?
Var b = 5;
var a = function() {
alert(b);
};
a();
Цель задачи: проверить понимание замыкания.
Тема: Замыкание (closure).
Ответ: Если исходить из определения замыкания — способность функции запоминать область видимости переменной, в которой та была объявлена, то правильный ответ 5. Функция a
запомнила содержимое объявленной ранее переменной за пределами функции, и после вывода функции, передала в alert 5.
Сколько угодно.
- Нужно алертом вывести какое-то сообщение, спустя 3 секунды после запуска скрипта. Как это сделать?
Так:
Или так:
- Чем отличается наследование в JavaScript от наследования в PHP?
В отличие от PHP, где наследование можно делать одним способом, в JavaScript таких способов много. На уровне языка реализовано наследование на прототипах.
В JavaScript каждый объект может иметь ассоциацию с другим объектом - так называемый "прототип" (prototype). В случае, если поиск некоторого свойства (или метода) в исходном объекте заканчивается неудачно, интерпретатор пытается найти одноименное свойство (метод) в его прототипе, затем - в прототипе прототипа и т. д. К примеру, если мы затребовали обращение к obj.prop (или, что абсолютно то же самое, obj["prop"]), JavaScript начнет искать свойство prop в самом объекте obj, затем – в прототипе obj, прототипе прототипа obj, и так до конца.
- Приведи пример наследования в JavaScript.
Например, пусть объект "cat" наследуется от объекта "animal".
В наследовании на прототипах это реализуется как ссылка
Или вот чуть более развернутый пример. MyType наследуется от Obj:
![](https://i0.wp.com/1.bp.blogspot.com/-bAs1n-Yo95A/V1EUnUErn0I/AAAAAAAAA1I/X-NYWY09PUMtOeZQa_RbY3rbI5BZfSqrgCLcB/s640/q005_p02.jpg)
- Пара слов об объектах в JavaScript?
Объекты (они же - ассоциативные массивы, хэши) и работа с ними в JavaScript реализованы не так, как в большинстве языков. Объект в JavaScript представляет собой обычный ассоциативный массив или, иначе говоря, "хэш". Он хранит любые соответствия "ключ => значение" и имеет несколько стандартных методов.
- Что представляет из себя метод объекта в JavaScript?
Метод объекта в JavaScript - это просто функция, которая добавлена в ассоциативный массив.
- Зачем в JavaScript перед переменной писать var?
Если создавать переменную через обычное присваивание - будет создана "глобальная переменная".
Пример:
Если создавать переменную с использованием слова var, тогда будет создана "локальная переменная", которая перестаёт существовать после завершения работы функции.
Пример:
- Есть две функции:
function f(a,b) { return a+b }
и
var f = function(a,b) { return a+b }.
Есть ли между ними разница? Если есть то какая?
Есть, разница в видимости функции. Вариант функции без var виден везде в текущей области видимости. В том числе и до самого определения функции. Вариант с var присваивает функцию переменной, поэтому такая функция видна только после определения.
- Как создать массив в JavaScript?
Вот несколько способов.
- Можно ли в JavaScript использовать функцию в качестве конструктора?
Вот так:
- Сколько и какие конструкции для циклов есть в JavaScript?
Три: for, while и do...while.
- Что cделает код: break mark; ?
Выйдет из текущего блока цикла или switch на метку "
mark
".
- Можно ли задать массив таким образом: var a = "a,b".split(",")?
Да, можно.
- Что выведет alert(typeof null); ?
Выведет сообщение "object".
- А это: alert(null instanceof Object); ?
Выведет сообщение "false".
- 0.1 + 0.2 == 0.3 ?
Нет, т.к. вычисленное значение будет равно 0.30000000000000004. Это действие точности вычислений и проявляется она не только в JavaScript.
- Что выведет alert(typeof NaN); ?
"Number"
- Что выведет alert(NaN === NaN); ?
"false"
- В чём различие свойств innerHTML и outerHTML?
Свойство любого DOM элемента innerHTML содержит HTML код, который находится внутри этого элемента. При установке нового значения этого свойства, внутренний HTML код рендерится браузером заново.
outerHTML почти аналогичен innerHTML, разница в том, что он возвращает полный HTML элемента.
Также, важно отметить, что innerHTML поддерживается всеми современными браузерами, а outerHTML поддерживается в IE (с некоторыми отличиями от остальных браузеров), в последних версиях Opera, и в браузерах на основе последних WebKit (Safari, Chrome), но не поддерживается в Firefox.
Для кода:
innerHTML возвратит:
outerHTML возвратит:
- Какая разница между операторами == и ===?
Оператор == сравнивает на равенство, а вот === сравнивает на идентичность. Плюс оператора === состоит в том, что он не приводит два значения к одному типу. Именно из-за этого он обычно и используется.
- В чем разница между Object.getOwnPropertyNames() и Object.keys()?
Object.getOwnPropertyNames() возвращает перечислимые и не перечислимые свойства из объекта или массива.
![](https://i2.wp.com/3.bp.blogspot.com/-kyryrsRS2I4/VvDbu1MikKI/AAAAAAAAAZc/an3yAcnVXJEWu3GBpnOsRGYpq67AuaCAw/s640/Object.getOwnPropertyNames%2528%2529.jpg)
Object.keys() возвращает перечислимые свойства из объекта или массива.
![](https://i2.wp.com/2.bp.blogspot.com/-7sGHvbgj0BQ/VvDb_a1pzZI/AAAAAAAAAZg/iwq7ZFMz0ZUSuBb9tjFnZMgIE57ra78Xg/s640/Object.keys%2528%2529.jpg)
- С помощью какой конструкции языка можно управлять потоком выполнения скрипта и отслеживать ошибки?
Это возможно с помощью конструкции try{}... catch{}
![](https://i2.wp.com/4.bp.blogspot.com/-yzgAqaF5c1I/VvDcUs--OTI/AAAAAAAAAZo/FnD8ChykGq40k3GWBuUzK-QLZNq_GBOcA/s640/try_catch.jpg)
- Почему вызов a(); происходит успешно, а вызов b(); выдает ошибку?
![](https://i0.wp.com/1.bp.blogspot.com/-vTEpmEmzvyo/VvDchDqwO_I/AAAAAAAAAZs/qp8h2g-KF8shPhkgx-SU1Nl9yijl8Qogg/s640/a%2528%2529.jpg)
Функция а() инициализируется на этапе загрузки скрипта, как бы "всплывает вверх" а функция б инициализируется, когда объявляется переменная b
- Что такое глобальные переменные? Как они создаются? Какие проблемы связаны с использованием глобальных переменных?
Глобальная переменная - переменная, которая доступна (видима) во всем документе, в отличии от локальной (ограничена рамками блока программного кода, внутри которого она определена)
Большинство JavaScript разработчиков избегает использования глобальных переменных. Одна из причин - возможный конфликт имен глобальных и локальных переменных. Так же код использующий глобальные переменные может быть тяжелее сопровождать и тестировать.
- Что такое замыкания (closure) в JavaScript?
Простыми словами это внутренняя функция, т.е. функция в функции.
Замыканием (closure) называют потому, что после выполнения родительской или внешней функции, код внутренней все еще "живет" в интерпретаторе, и его можно выполнить. Ошибок не возникнет даже если внутренняя функция (замыкание) будет использовать переменные из внешней функции.
Например, эту особенность можно использовать для создания функций обработчиков событий:
![](https://i1.wp.com/1.bp.blogspot.com/-VoBTylP0Cs8/VvDdP6N1vCI/AAAAAAAAAaA/StT6Ehw9h2g6kl-mYPQMWUfk1j_CfqgAA/s640/closure.jpg)
- Напишите функцию принимающую строку с именем файла и возвращающую расширение (фрагмент после последней точки).
- Что такое prototype в javascript?
В общих чертах prototype - это свойство позволяющее добавлять уже существующим объектам свойства, также используется для эмуляции наследования классов в JavaScript. Подробный ответ написан здесь. Еще как вариант, можно упомянуть о Prototype.js. Это популярная библиотека добавляющая удобные ООП возможности в программы на JavaScript-е.
- Какие способы навешивания обработчиков событий вы знаете?
События можно добавлять тремя способами:
- htmlElement.onclick = function(event) { .... } - так можно добавить только один обработчик
- htmlElement.addEventListener("click", ...) - так можно навесить несколько обработчиков, сохраняет порядок обработчиков
- htmlElement.attachEvent("on"+имя_события, обработчик) - тоже можно навесить несколько, не сохраняет порядок обработчиков, нет доступа к элементу на котором сработало событие.