Продолжаем разбирать часто задаваемые вопросы на интервью.
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 и с. </pre> Теперь сделаем тоже самое, только вывод 'а' обернем в setTimeout(). <pre lang="js"> 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
Напоследок, хотелось бы посоветовать не спешить с ответами при прохождении собеседования, особенно на вопросы, связанные с анализом предложенного кода. Часто очевидные на первый взгляд вопросы содержат хитрости и ловушки. Остановитесь, подумайте лишнюю минутку. Задайте уточняющие вопросы — это продемонстрирует вашу внимательность и ответственное отношение к делу. Поможет выявить интервьюверу ход ваших мыслей. Собственно, в основном для этого и задаются хитрые или сложные задачи. Гораздо важнее продемонстрировать правильное мышление, даже если ответ на вопрос в итоге будет неверным.
Человек не может знать всё, это в принципе невозможно. Часто бывает так, что на прошлой работе вы сталкивались с одними технологиями и приёмами, а на новой команда имеет другие взгляды на архитектуру и пользуется не очень знакомыми вам библиотеками. Вот почему грамотный интервьювер в первую очередь постарается выяснить, что за человек перед ним, как он мыслит, его аналитические способности. В конце концов, недостающие пробелы заполнить очень легко, чего нельзя сказать о правильном мышлении программиста, которое формируется только с опытом.
root4root aka admin
Спасибо за статью! Сейчас готовлюсь к собеседованию, читаю такого рода материалы.
У вас опечатка:
setI(b) {
i = k;
},
Наверное:
setI(b) {
i = b;
},
Да, конечно же вы правы! Спасибо, исправил.