JavaScript. Вопросы на собеседовании
Не так давно озадачился поиском работы, в связи с чем посетил n-нное количество собеседований и услышал много интересных вопросов. По сети гуляет много статей с вопросами по JS, поэтому постараюсь выбрать вопросы, которые ещё не видел. Здесь нет вопросов типа Что такое замыкание?, Наследование в JavaScript или Сделайте ajax запрос на VanillaJS. Кстати советую поискать ответы на эти вопросы, прежде чем читать статью :) Под катом вопросы типа «с подвохом». Вряд ли какой-то из них попадётся вам, но, надеюсь, статья настроит вас на «подвоховое» мышление, и напомнит некоторые скользкие места и подводные камушки javascript.HoistingHoisting — всплытие переменных объявленных в функции.Здесь можно подробно узнать о том как это бывает.А вот интересный вопрос: (function () { f ();
f = function () { console.log (1); } })()
function f () { console.log (2) }
f (); Что мы увидим в консоли?
Ответ Объявленная в gs function f () всплывёт, соответственно при вызове f внутри анонимной функции мы увидим не ReferenceError, как кто-то мог предположить, а двойку в консоли, при повторном вызове переменная f уже ссылается на функцию которая печатает 1.Результат:
< (function() { f();
f = function () { console.log (1); } })()
function f () { console.log (2) }
f (); > undefined 2 1 Если вы сходу уловили подвох предыдущей задачи — не обольщайтесь. Вот ещё интересный пример кода:
(function () { var x = 1;
function x () {}; console.log (x); })() Что теперь мы увидим в консоли?
Ответ Функции объявленный при помощи function declaration имеют больший приоритет и понимаются выше var. Поэтому интерпретатор сначала выполнит function x () {};, а затем var x = 1; < (function() {var x = 1;
function x () {};
console.log (x);})()
> undefined1
Ну и напоследок. Напомню советы Дугласа Крокфорда: избегать слабых сторон языка и использовать сильные и использовать JSLint.Чтобы не наткнуться на такие сюрпризы можно взять за привычку самому выносить var в начало функции и объявлять функцию через function expression
Передача по ссылке Наверное все знают что все объекты передаются в javascript по ссылке:
var obj = { a: 1 }
(function (obj) { obj = { a: 2 };
})(obj);
console.log (obj.a); Не знаю как вы, а я засыпался на этом вопросе. Я точно знал что объект не измениться после вызова функции, но объяснить почему так и не смог.
А вот почему! При вызове анонимной функции создастся локальная переменная obj в её области видимости. А затем создаётся новый объект {a: 2}, ссылка на который попадает в локальную переменную obj, но переменная из верхнего скоупа будет всё так же ссылаться на старый объект.
Контекст выполнения Контекст выполнения функции — мощный и выразительный механизм, если умело его использовать. Правда есть несколько моментов о которых не стоит забывать. Простой пример. Рассмотрим класс который логгирует некие действия.
Logger = function (logFn) { _logFn = logFn;
this.log = function (message) { _logFn (new Date () + »:» + message); } }
var logger = new Logger (console.log);
logger.log («Hi!»); logger.log («Wazzup?»); Что будет в консоли? Как починить?
Ответ В консоли мы увидим TypeError: Illegal invocationА всё потому что при вызове logger.log (), контекст выполнения функции — loggerЧтобы починить можно вспомнить про встроенные методы функций .apply (), .call (), .bind ()
< rightLogger = new Logger(console.log.bind(console)) > Logger {log: function} < rightLogger.log("It's works") > Sat Oct 04 2014 00:32:49 GMT+0400 (MSK): It’s works