Идеальное руководство для прохождения интервью JavaScript- разработчика.
Интервью с JavaScript (JS) непросты. Я принимаю это, вы принимаете его, и каждый делает это. Количество возможностей вопросов, которые можно задать в интервью для JavaScript, велико. Как можно пройти интервью JS? Когда начать? Эта статья - попытка проинструктировать всех начинающих разработчиков JavaScript, чтобы углубить их знания JS, зная основные концепции. Это первые шаги, которые нужно предпринять, по крайней мере, для интервью JS. Если я кандидат, я хорошо готовлю эти концепции. Если я интервьюер, я предполагаю, что вы знаете, что бы продолжить дальше.
Если вы не знаете автора,то он является разработчиком полного стека с опытом работы с Python, Go & JavaScript. Недавно он написал книгу- "Building RESTful Web services with Go"!
Это руководство является отправной точкой, но не является толчком для разработчика JS. Это его / ее обязанность готовиться к гораздо более жестким интервью. Им также необходимо иметь в виду, что вопросы собеседования также могут быть связаны с доменом и технологиями, которые они работали (например: React JS, WebPack, Node JS и т. Д.).
Здесь мы представляем основные элементы JS, которые вы должны хорошо разбираться, чтобы назвать себя хорошим разработчиком JavaScript.
Прекрасный разработчик JS может быть отличным разработчиком React, но обратное не гарантируется. К сожалению, JS имеет плохую репутацию для производства бесчисленных сценаристов с отсутствием дисциплины (частично верно). JavaScript позволяет разработчикам делать что-либо, без полного понимания. Это тоже забавно. Немногие великие программисты на JavaScript, такие как Джон Ресиг (создатель, jQuery), Брендан Эйч (создатель, JS), и Ларс Бак (команда Google Chrome) понимали язык от и до. Успешный программист JS всегда читает простой JS-код из библиотек. Многие говорят, что очень сложно найти хорошего разработчика JavaScript.
Чтобы показать вам сложность интервью JS, с первого взгляда попытайтесь выяснить исход этого заявления JS.
9 человек из 10 говорят, что это печатает
JavaScript- язык жесткий. Мы не можем сделать многого, если интервьюер слишком умный, чтобы задавать такие вопросы, как выше. Но что мы можем сделать? Глубоко изучите эти одиннадцать основных элементов, чтобы превратить JS-интервью, в благоприятное для вас.
Я не собираюсь объяснять, что здесь является функцией, но знаете ли вы, что малые вещи тоже могут вас удивить? Как это!
Этот фрагмент кода выведет 25. True! См. Второй фрагмент кода
На первый взгляд, у вас может возникнуть соблазн сказать, что это тоже печатает 25. False! Но вместо этого вы получите ошибку уже при обработке кода.
В JavaScript, если вы определяете функцию как переменную, имя переменной будет поднято (hoisted), и вы не сможете получить доступ, пока выполнение JS не встретит её объявления . Вы не удивлены?
Оставим это. Возможно, вы часто видели этот синтаксис где-то в некотором коде.
Почему люди делают такие странные вещи? Это функциональная переменная, которая имеет инкапсулированные переменные и функции, которые не загрязняют глобальную область. Библиотеки от jQuery до Lodash используют эту технику, чтобы предоставить вам переменные типа
То, что я здесь представил, - «учиться хорошо». Мы используем много тонких ловушек. Прочитайте хорошо написанную запись Mozilla о функциях. Functions
В принципе, это прототип методов функций для изменения их поведения для достижения чего-то. Согласно Чаду, разработчику JS, использование похоже на это:
Вы отправили библиотеку профессору. Теперь пришло время представить код, который вызывает эту математическую библиотеку.
Представляя образцы второго кода, вы нашли в рекомендациях, что профессор попросил вас использовать постоянный pi с точностью до пяти десятичных знаков. О Боже! Вы только что использовали 3.14, а не 3.14159. Теперь у вас нет возможности отправить библиотеку по истечении крайнего срока. Функция вызова - Call JS спасет вас. Просто вызвать
и функция принимает ваше новое значение pi на лету. Выведет:
Это сделает вашего профессора счастливым! Если вы заметили, функция вызова - Call принимает два аргумента:
Контекст - это объект, который заменяет это ключевое слово внутри функции области. Позже аргументы передаются как аргументы функции. Для Ex:
ВызовCall выглядит следующим образом:
Вы увидели, что эти аргументы функции передаются в качестве последующих аргументов после объекта контекста.
Apply точно также, только вместо аргументов передает список:
Если вы знаете call, вы знаете apply и наоборот. Теперь, что такое bind?
Bind придает новое значение данной функции. В случае с Bind функция не запускается мгновенно, как например Call или Apply.
Какая польза от Bind? Это позволяет нам вводить контекст в функцию, которая возвращает новую функцию с обновленным контекстом. Это означает, что эта переменная будет использоваться пользователем. Это очень полезно при работе с событиями JavaScript.
Глобальная область - это то, что мы обычно делаем:
Область функции представлена так, когда вы определяете переменную локально.
Стандарт ES16 ввел новую область блока, которая ограничивает область переменной для данного блока внутри скобок.
Функции и условия рассматриваются как блоки. Вышеприведенный пример должен предупредить 4, поскольку выполняются условные операторы. Но ES6 уничтожает область блоков переменных, и область охвата перешла в глобальную.
Теперь наступает просто магия области видимости (scope). Это может быть достигнуто с помощью закрытий (closures). Закрытие (closures) JavaScript - это функция, которая возвращает другую функцию.
Если кто-то задаст вам этот вопрос. Напишите пример, который принимает строку и сразу возвращает символ. Если задана новая строка, она должна заменить старую. Это просто называется генератором.
Исполнение идет таким образом!
Здесь область видимости (scope) играет важную роль. Закрытие - это функция, которая возвращает другую функцию и обертывает данные. Вышеуказанный генератор строк представляет замыкание. Значение индекса сохраняется между несколькими вызовами функций. Внутренняя функция может обращаться к переменным, определенным в родительской функции. Это разная область. Если вы определили еще одну функцию в функции второго уровня, которая может получить доступ ко всем родительским переменным.
Когда изменяется контекст и область видимости (scope) программных изменений, this в этом конкретном пункте изменяется соответствующим образом. Теперь см. this в локальном контексте:
Теперь у вас возникнет соблазн предсказать этот результат.
Нет, не будет. Потому что здесь this ссылается на глобальный объект. Помните, каков бы ни был родительский охват, он будет унаследован дочерним элементом. Таким образом, здесь будет выведен объект окна (window object). Три метода, которые мы обсуждали, фактически используются для установки this объекта.
Теперь идет последний тип this - this в области объекта. Вот так:
Я просто использовал синтаксис getter, который является функцией, которую можно вызвать как переменную.
Здесь this фактически относится к самому объекту. И this, как мы уже говорили ранее, ведет себя по-разному в разных местах. Это следует очень хорошо знать.
Это пример объекта, в котором хранятся пары Key- ключи, Value - значения. Объекты JavaScripts имеют особое свойство хранить что-либо как значение. Это означает, что мы можем сохранить список, другой объект, функцию и т. д. В качестве значения. Почему бы и нет?
Вы можете создать объект таким образом:
Вы можете легко преобразовать заданный объект в строку JSON, а также преобразовать его обратно с помощью методов строкового и синтаксического анализа объектов JSON соответственно.
Итак, какие еще мелочи об объектах, которые вы должны знать? Простую итерацию объекта, используя Object.keys.
Object.values возвращает список значений объекта.
Другими важными функциями для объекта являются:
Object.prototype предоставляет более важные функции, которые имеют множество приложений. Некоторые из них:
Object.prototype.hasOwnProperty полезен, чтобы узнать, существует ли данное свойство / ключ в объекте.
Object.prototype.instanceof оценивает, является ли данный объект типом определенного прототипа (мы увидим их в следующем разделе, это функции).
Теперь идут две другие функции.Object.freeze позволяет нам заморозить объект, чтобы существующие свойства не могли быть изменены.
Здесь мы пытаемся изменить значение свойства
Object.seal немного отличается от freeze замораживания. Он позволяет изменять свойства, но не позволяет добавлять или удалять новые свойства или свойства.
Мы также можем проверить, закрыт ли данный объект, используя этот
Существует множество других важных функций / методов, доступных для функции Global Object. Найдите их здесь. Object
Здесь мы создаем объекты для класса (используя новое ключевое слово). Мы можем добавить методы для данного класса (функции), подобные этому. Прикрепить метод класса, подобный this.
Здесь можно усомниться в правильности. В классе нет свойства звука - sound property. Да! вряд ли определяется sound property. Но таким образом это предназначено для передачи дочерними классами, которые наследуют класс далее.
В JavaScript наследование достигается таким образом.
Я определил еще одну специальную функцию под названием Dog. Здесь, чтобы наследовать класс Animal, нам нужно выполнить функцию вызова call (мы обсуждали ее ранее) с передачей this и других аргументов. Мы можем создать экземпляр German Shepard.
Мы не назначаем имя и тип дочерней функции, мы вызываем супер функцию Animal и устанавливаем соответствующие свойства. Домашнее животное имеет свойства (имя, тип) родителя. Но как насчет методов. Наследуются ли они тоже? Давайте посмотрим!
Как же так? Почему это произошло? Это происходит потому, что мы не сказали JavaScript, чтобы наследовать методы родительского класса. Как это исправить?
Теперь method доступен. Мы можем проверить, что является классом данного объекта в JavaScript, используя функцию object.constructor. Давайте посмотрим, что предсавляет класс нашего питомца - pet.
Это расплывчато. Animal - родительский класс. Но какой именно тип pet ? Это Dog type. Это происходит из-за конструктора Dog class.
Эти четыре вещи, которые вы должны помнить о прототипическом наследовании.
Здесь reqListener - это обратный вызов, который будет выполняться, когда запрос GET успешно возвращается.
Обещания (promises) - это аккуратные обертки для обратных вызовов, которые позволяют нам запускать асинхронный код элегантно. Я много обсуждал здесь обещания. Это также важный элемент, который должен быть известен всем в JS. Writing neat asynchronous Node JS code with Promises
Мы можем создать новое регулярное выражение, используя это
Вышеприведенное регулярное выражение является выражением, которое соответствует заданному набору строк. Как только регулярное выражение определено, мы можем попытаться подобрать и увидеть соответствующую строку. мы можем сопоставить строки с помощью функции exec (exec function).
Существует несколько специальных классов символов, которые позволяют нам писать сложные регулярные выражения.
В RegEx существует много типов элементов. Некоторые из них:
Используя приведенные выше вещи, давайте проиллюстрируем несколько примеров.
Для получения дополнительной информации о регулярном выражении, пройдите по ссылке Quick-Start: Regex Cheat Sheet.
Наряду с exec существуют и другие функции, а именно match, search и, replace доступны для поиска строки в другой с использованием регулярных выражений. Но эти функции должны использоваться в строковых выражениях.
Regex - важная тема, которую разработчики должны легко понимать для решения сложных задач.
Предположим, есть несколько нежелательных символов, введенных в серийные ключи, с которыми мы работаем в последнее время. Нам нужно их удалить. Вместо удаления символа путем итерации и поиска мы можем использовать map для выполнения той же операции и получения массива результатов.
map принимает функцию в качестве аргумента. Эта функция имеет аргумент. Этот аргумент выбирается из массива. Нам нужно вернуть обработно элемент, который будет применим ко всем элементам массива.
Другими словами мы хотим выполнить определенные действия с каждым элементом массива.
Одним из практических приложений для reduce может быть сглаживание массива массивов. Сглаживание (Flattening) преобразует внутренние массивы в один массив. Для Ex:
Мы можем добиться этого путем обычной итерации. Но, используя сокращение, это более читабельный и простой код. Магия!
Здесь elem - это элемент данных массива, и true / false следует возвращать из функции, чтобы указать включение / исключение фильтрованного элемента. Общим примером является фильтрация массива слов, который начинается и заканчивается заданными условиями. Предположим, мы должны отфильтровать массив слов, начинающийся с t и заканчивающийся на r.
Эти три функции должны быть у вас под рукой, когда кто-то спрашивает вас о функциональных аспектах программирования JavaScript. Как вы видите, исходный массив не изменяется во всех трех случаях, которые доказывают чистоту этих функций.
Николас К. Закас (Nicholas C. Zakas), инженер UI в Yahoo, сказал в 2008 году: "Всегда предполагайте, что ваш код не удастся. Невозможно правильно обработать события! Запишите их на сервер. Брось свои ошибки."
В JavaScript всякий раз, когда мы кодируем, мы всегда можем потерпеть неудачу. Для Ex:
Здесь мы попадаем в ловушку, говоря, что результаты всегда будут объектом JSON. Иногда сервер может сбой, и вместо результата возвращается null. В этом случае null ["posts"] выдаст ошибку. Правильное обращение может быть таким!
Функция logError предназначена для сообщения об ошибке на сервере. Вторая функция flashInfoMessage- это функция, которая отображает удобное для пользователя сообщение типа «Сервис недоступен в настоящее время» и т. д.
Николас говорит, что каждый раз, когда вы чувствуете, что-то неожиданное произойдет, вы будете ловить ошибки. Различают фатальные и нефатальные ошибки. Вышеприведенная ошибка связана с тем, что сервер backend упал, что является фатальным. Таким образом вы должны сообщить клиенту, что по какой-то причине служба отключена. В некоторых случаях это может быть не смертельным, но лучше уведомлять об этом. Чтобы создать такой код, сначала выведите ошибку, поймайте ее с событием ошибки на уровне объекта
Этот код в основном выполняет три функции:
Вы также можете использовать новую функцию Boolean (ES5, ES6), чтобы проверить, действительна ли переменная, а не null (или) не определена, прежде чем продолжить.
Всегда думайте, как обращаться с ошибками. Все может закончиться неудачей!
Когда вы делаете что-то выше на языке сценариев, таком как Python, он выдает ошибку. Вы должны сначала определить что-то (переменную, функцию), а уже потом использовать это. Несмотря на то, что JS является языком сценариев, у него есть механизм подъема. В этом механизме, во время работы программы, во время работы с программой Java VM делает две вещи:
В приведенном выше фрагменте кода console.log печатает "undefined". Это потому, что в первом проходе собрана переменная foo. VM ищет любое значение, определенное для переменной foo. Этот подъем может привести ко многим ситуациям кода JavaScript, где код может вызывать ошибки в некоторых местах и использовать неопределенное значения по умолчанию, в другом. Вы должны знать подъем hosting , чтобы очистить ваш код от двусмысленности! Несколько примеров! Hoisting
При барботировании событие сначала захватывается и обрабатывается самим внутренним элементом, а затем распространяется на внешние элементы. С захватом процесс идет обратным образом. Обычно мы прикрепляем событие к обработчику, используя функцию addEventListener.
Третий аргумент useCapture - это ключ. Значение по умолчанию неверно. Таким образом, это будет пузырящая модель, в которой событие сначала обрабатывается самым внутренним элементом, и оно распространяется наружу, пока не достигнет родительского элемента. Если этот аргумент верен, он захватывает модель.
Для Ex: Bubbling Model
Когда мы нажимаем элемент списка, порядок выполнения обработчиков подобен порядковому номеру (по умолчанию).
На диаграмме обработчики последовательно запускаются наружу. Аналогично, модель захвата пытается инициировать события от родителя до щелчка элемента. Теперь измените эту строку в приведенном выше коде.
Порядок выполнения обработчиков будет следующим:
Вы должны понимать, что пузырь событий (event bubbling) (независимо от направления движения к родительскому элементу или к ребенку) должным образом реализует пользовательские интерфейсы (UI), чтобы избежать нежелательного поведения.
Это основные понятия JavaScript. Как я уже упоминал ранее, дополнительная информация о них, ваш опыт работы и знания, подготовка поможет вам пройти интервью с JavaScript. Всегда продолжайте учиться. Следите за последними событиями (ES6). Копайте глубже в различных аспектах JavaScript, таких как двигатель V6, тесты и т. д. Здесь представлено несколько видео ресурсов, которые научат вас многим вещам.
Object.prototype.constructor
Using XMLHttpRequest
Regular Expressions
What is event bubbling and capturing?
123-Essential-JavaScript-Interview-Question
Автор: Naren Arya, перевел Ярослав Колесников.
Интервью с JavaScript (JS) непросты. Я принимаю это, вы принимаете его, и каждый делает это. Количество возможностей вопросов, которые можно задать в интервью для JavaScript, велико. Как можно пройти интервью JS? Когда начать? Эта статья - попытка проинструктировать всех начинающих разработчиков JavaScript, чтобы углубить их знания JS, зная основные концепции. Это первые шаги, которые нужно предпринять, по крайней мере, для интервью JS. Если я кандидат, я хорошо готовлю эти концепции. Если я интервьюер, я предполагаю, что вы знаете, что бы продолжить дальше.
Если вы не знаете автора,то он является разработчиком полного стека с опытом работы с Python, Go & JavaScript. Недавно он написал книгу- "Building RESTful Web services with Go"!
Это руководство является отправной точкой, но не является толчком для разработчика JS. Это его / ее обязанность готовиться к гораздо более жестким интервью. Им также необходимо иметь в виду, что вопросы собеседования также могут быть связаны с доменом и технологиями, которые они работали (например: React JS, WebPack, Node JS и т. Д.).
Здесь мы представляем основные элементы JS, которые вы должны хорошо разбираться, чтобы назвать себя хорошим разработчиком JavaScript.
Прекрасный разработчик JS может быть отличным разработчиком React, но обратное не гарантируется. К сожалению, JS имеет плохую репутацию для производства бесчисленных сценаристов с отсутствием дисциплины (частично верно). JavaScript позволяет разработчикам делать что-либо, без полного понимания. Это тоже забавно. Немногие великие программисты на JavaScript, такие как Джон Ресиг (создатель, jQuery), Брендан Эйч (создатель, JS), и Ларс Бак (команда Google Chrome) понимали язык от и до. Успешный программист JS всегда читает простой JS-код из библиотек. Многие говорят, что очень сложно найти хорошего разработчика JavaScript.
«Виртуальные машины - странный зверь. Идеального решения нет, вместо этого вы оптимизируете «идеальное место». Там много мастерства. Это долгая игра, вы не можете сгореть »- Ларс Бак, Google
Чтобы показать вам сложность интервью JS, с первого взгляда попытайтесь выяснить исход этого заявления JS.
console.log(2.0 == “2” == new Boolean(true) == “1”)
9 человек из 10 говорят, что это печатает
false
. Но он печатает true
. Почему? См. здесь.
JavaScript- язык жесткий. Мы не можем сделать многого, если интервьюер слишком умный, чтобы задавать такие вопросы, как выше. Но что мы можем сделать? Глубоко изучите эти одиннадцать основных элементов, чтобы превратить JS-интервью, в благоприятное для вас.
1) Хорошо понимать функции JS
Функции - это сливки JavaScript. Это граждане первого класса. Без глубокого знания функций JS, ваши знания сильно ограничены. Функция JS больше чем, просто функция. В отличие от других языков, функция может быть назначена переменной, переданной как аргумент другой функции и также может быть возвращена из другой. Следовательно, это гражданин первого класса в JS.Я не собираюсь объяснять, что здесь является функцией, но знаете ли вы, что малые вещи тоже могут вас удивить? Как это!
console.log(square(5)); /* ... */ function square(n) { return n * n; }
Этот фрагмент кода выведет 25. True! См. Второй фрагмент кода
console.log(square(5)); var square = function(n) { return n * n; }
На первый взгляд, у вас может возникнуть соблазн сказать, что это тоже печатает 25. False! Но вместо этого вы получите ошибку уже при обработке кода.
TypeError: square is not a function
В JavaScript, если вы определяете функцию как переменную, имя переменной будет поднято (hoisted), и вы не сможете получить доступ, пока выполнение JS не встретит её объявления . Вы не удивлены?
Оставим это. Возможно, вы часто видели этот синтаксис где-то в некотором коде.
var simpleLibrary = function() { var simpleLibrary = { a, b, add: function(a, b) { return a + b; }, subtract: function(a, b) { return a - b; } } return simpleLibrary; }();
Почему люди делают такие странные вещи? Это функциональная переменная, которая имеет инкапсулированные переменные и функции, которые не загрязняют глобальную область. Библиотеки от jQuery до Lodash используют эту технику, чтобы предоставить вам переменные типа
$
и т. Д.
То, что я здесь представил, - «учиться хорошо». Мы используем много тонких ловушек. Прочитайте хорошо написанную запись Mozilla о функциях. Functions
2) Понимание bind, apply и call
Эти функции вы можете увидеть во всех известных библиотеках. Они позволяют делать что-то названное currying, используя их мы можем скомпоновать функциональность в разные функции. Хороший разработчик JavaScript может рассказать вам о них в любое время дня и ночи.В принципе, это прототип методов функций для изменения их поведения для достижения чего-то. Согласно Чаду, разработчику JS, использование похоже на это:
Используйте
.bind ()
, когда вы хотите, чтобы эта функция позже вызывалась с определенным контекстом, полезным в событиях. Используйте .call ()
или .apply ()
, когда вы хотите немедленно вызвать функцию, с изменением контекста.Бережный вызов (saving call)
Давайте посмотрим, что означает это утверждение! Предположим, ваш учитель математики попросил вас создать библиотеку и отправить ее. Вы написали абстрактную библиотеку, которая находит область и окружность круга.var mathLib = { pi: 3.14, area: function(r) { return this.pi * r * r; }, circumference: function(r) { return 2 * this.pi * r; } };
Вы отправили библиотеку профессору. Теперь пришло время представить код, который вызывает эту математическую библиотеку.
mathLib.area(2); 12.56
Представляя образцы второго кода, вы нашли в рекомендациях, что профессор попросил вас использовать постоянный pi с точностью до пяти десятичных знаков. О Боже! Вы только что использовали 3.14, а не 3.14159. Теперь у вас нет возможности отправить библиотеку по истечении крайнего срока. Функция вызова - Call JS спасет вас. Просто вызвать
.call()
своему коду таким образом:
mathLib.area.call({pi: 3.14159}, 2);
и функция принимает ваше новое значение pi на лету. Выведет:
12.56636
Это сделает вашего профессора счастливым! Если вы заметили, функция вызова - Call принимает два аргумента:
- Context - контекст.
- Function arguments - аргументы функции.
Контекст - это объект, который заменяет это ключевое слово внутри функции области. Позже аргументы передаются как аргументы функции. Для Ex:
var cylinder = { pi: 3.14, volume: function(r, h) { return this.pi * r * r * h; } };
Вызов
cylinder.volume.call({pi: 3.14159}, 2, 6); 75.39815999999999
Вы увидели, что эти аргументы функции передаются в качестве последующих аргументов после объекта контекста.
Apply точно также, только вместо аргументов передает список:
cylinder.volume.apply({pi: 3.14159}, [2, 6]); 75.39815999999999
Если вы знаете call, вы знаете apply и наоборот. Теперь, что такое bind?
Bind придает новое значение данной функции. В случае с Bind функция не запускается мгновенно, как например Call или Apply.
var newVolume = cylinder.volume.bind({pi: 3.14159}); // This is not instant call // After some long time, somewhere in the wild newVolume(2,6); // Now pi is 3.14159
Какая польза от Bind? Это позволяет нам вводить контекст в функцию, которая возвращает новую функцию с обновленным контекстом. Это означает, что эта переменная будет использоваться пользователем. Это очень полезно при работе с событиями JavaScript.
Вы должны знать эти три функции для создания функциональности в JavaScript.
3) Хорошо понимать области видимости JavaScript (И скрытые области также)
Область видимости (scope) JavaScript - это ящик пандоры. Сотни сложных вопросов интервью могут быть сформулированы из этой единой концепции. Существует три вида областей видимости (scope):- Global scope - глобальная
- Local Scope/Function scope - локальная (функциональная).
- Block scope(Introduced in ES6)- блочная. Представленная в ES6
Глобальная область - это то, что мы обычно делаем:
x = 10; function Foo() { console.log(x); // Prints 10 } Foo()
Область функции представлена так, когда вы определяете переменную локально.
pi = 3.14; function circumference(radius) { pi = 3.14159; console.log(2 * pi * radius); // Prints "12.56636" not "12.56" } circumference(2);
Стандарт ES16 ввел новую область блока, которая ограничивает область переменной для данного блока внутри скобок.
var a = 10; function Foo() { if (true) { let a = 4; } alert(a); // alerts '10' because the 'let' keyword } Foo();
Функции и условия рассматриваются как блоки. Вышеприведенный пример должен предупредить 4, поскольку выполняются условные операторы. Но ES6 уничтожает область блоков переменных, и область охвата перешла в глобальную.
Теперь наступает просто магия области видимости (scope). Это может быть достигнуто с помощью закрытий (closures). Закрытие (closures) JavaScript - это функция, которая возвращает другую функцию.
Если кто-то задаст вам этот вопрос. Напишите пример, который принимает строку и сразу возвращает символ. Если задана новая строка, она должна заменить старую. Это просто называется генератором.
function generator(input) { var index = 0; return { next: function() { if (index < input.length) { index += 1; return input[index - 1]; } return ""; } } }
Исполнение идет таким образом!
var mygenerator = generator("boomerang"); mygenerator.next(); // returns "b" mygenerator.next() // returns "o" mygenerator = generator("toon"); mygenerator.next(); // returns "t"
Здесь область видимости (scope) играет важную роль. Закрытие - это функция, которая возвращает другую функцию и обертывает данные. Вышеуказанный генератор строк представляет замыкание. Значение индекса сохраняется между несколькими вызовами функций. Внутренняя функция может обращаться к переменным, определенным в родительской функции. Это разная область. Если вы определили еще одну функцию в функции второго уровня, которая может получить доступ ко всем родительским переменным.
Область видимости (scope) JavaScript может доставить вам массу проблем! Стоит полностью понимать это.
4) Понимайте это ключевое слово well (глобальное, функциональное и предметное пространство - global, function and object scopes)
В JavaScript мы всегда составляем код с функциями и объектами. Если вы используете браузер, то в глобальном контексте он ссылается на объект окна (window object). Я имею в виду, что это будет оцениваться как true, если вы сейчас откроете консоль браузера и введите это.this === window;
Когда изменяется контекст и область видимости (scope) программных изменений, this в этом конкретном пункте изменяется соответствующим образом. Теперь см. this в локальном контексте:
function Foo(){ console.log(this.a); } var food = {a: "Magical this"}; Foo.call(food); // food is this
Теперь у вас возникнет соблазн предсказать этот результат.
function Foo(){ console.log(this); // prints {}? }
Нет, не будет. Потому что здесь this ссылается на глобальный объект. Помните, каков бы ни был родительский охват, он будет унаследован дочерним элементом. Таким образом, здесь будет выведен объект окна (window object). Три метода, которые мы обсуждали, фактически используются для установки this объекта.
Теперь идет последний тип this - this в области объекта. Вот так:
var person = { name: "Stranger", age: 24, get identity() { return {who: this.name, howOld: this.age}; } }
Я просто использовал синтаксис getter, который является функцией, которую можно вызвать как переменную.
person.identity; // returns {who: "Stranger", howOld: 24}
Здесь this фактически относится к самому объекту. И this, как мы уже говорили ранее, ведет себя по-разному в разных местах. Это следует очень хорошо знать.
5) Хорошо понимать объекты (Object.freeze, Object.seal)
Многие из нас знают такие объекты.var marks = {physics: 98, maths:95, chemistry: 91};
Это пример объекта, в котором хранятся пары Key- ключи, Value - значения. Объекты JavaScripts имеют особое свойство хранить что-либо как значение. Это означает, что мы можем сохранить список, другой объект, функцию и т. д. В качестве значения. Почему бы и нет?
Вы можете создать объект таким образом:
var marks = {}; var marks = new Object();
Вы можете легко преобразовать заданный объект в строку JSON, а также преобразовать его обратно с помощью методов строкового и синтаксического анализа объектов JSON соответственно.
// returns "{"physics":98,"maths":95,"chemistry":91}" JSON.stringify(marks); // Get object from string JSON.parse('{"physics":98,"maths":95,"chemistry":91}');
Итак, какие еще мелочи об объектах, которые вы должны знать? Простую итерацию объекта, используя Object.keys.
var highScore = 0; for (i of Object.keys(marks)) { if (marks[i] > highScore) highScore = marks[i]; }
Object.values возвращает список значений объекта.
Другими важными функциями для объекта являются:
- Object.prototype(object)
- Object.freeze(function)
- Object.seal(function)
Object.prototype предоставляет более важные функции, которые имеют множество приложений. Некоторые из них:
Object.prototype.hasOwnProperty полезен, чтобы узнать, существует ли данное свойство / ключ в объекте.
marks.hasOwnProperty("physics"); // returns true marks.hasOwnProperty("greek"); // returns false
Object.prototype.instanceof оценивает, является ли данный объект типом определенного прототипа (мы увидим их в следующем разделе, это функции).
function Car(make, model, year) { this.make = make; this.model = model; this.year = year; } var newCar = new Car('Honda', 'City', 2007); console.log(newCar instanceof Car); // returns true
Теперь идут две другие функции.Object.freeze позволяет нам заморозить объект, чтобы существующие свойства не могли быть изменены.
var marks = {physics: 98, maths:95, chemistry: 91}; finalizedMarks = Object.freeze(marks); finalizedMarks["physics"] = 86; // throws error in strict mode console.log(marks); // {physics: 98, maths: 95, chemistry: 91}
Здесь мы пытаемся изменить значение свойства
physics
после замораживания объекта. Но JavaScript не позволит этого сделать. Мы можем определить, заблокирован ли данный объект или нет.
Object.isFrozen(finalizedMarks); // returns true
Object.seal немного отличается от freeze замораживания. Он позволяет изменять свойства, но не позволяет добавлять или удалять новые свойства или свойства.
var marks = {physics: 98, maths:95, chemistry: 91}; Object.seal(marks); delete marks.chemistry; // returns false as operation failed marks.physics = 95; // Works! marks.greek = 86; // Will not add a new property
Мы также можем проверить, закрыт ли данный объект, используя этот
Object.isSealed(marks); // returns true
Существует множество других важных функций / методов, доступных для функции Global Object. Найдите их здесь. Object
6) Хорошо понимать прототипное наследование - Prototypical Inheritance
В традиционном JavaScript существует концепция скрытого наследования. Это использование технологии прототипирования. Все новые class syntax , которые вы видите в ES5, ES6 - это просто синтаксическое представление для базового прототипироания, лежащего в основе ООП. Создание класса в JavaScript, выполняется с помощью функции.var animalGroups = { MAMMAL: 1, REPTILE: 2, AMPHIBIAN: 3, INVERTEBRATE: 4 }; function Animal(name, type) { this.name = name; this.type = type; } var dog = new Animal("dog", animalGroups.MAMMAL); var crocodile = new Animal("crocodile", animalGroups.REPTILE);
Здесь мы создаем объекты для класса (используя новое ключевое слово). Мы можем добавить методы для данного класса (функции), подобные этому. Прикрепить метод класса, подобный this.
Animal.prototype.shout = function() { console.log(this.name + 'is ' + this.sound + 'ing...'); }
Здесь можно усомниться в правильности. В классе нет свойства звука - sound property. Да! вряд ли определяется sound property. Но таким образом это предназначено для передачи дочерними классами, которые наследуют класс далее.
В JavaScript наследование достигается таким образом.
function Dog(name, type) { Animal.call(this, name, type); this.sound = "bow"; }
Я определил еще одну специальную функцию под названием Dog. Здесь, чтобы наследовать класс Animal, нам нужно выполнить функцию вызова call (мы обсуждали ее ранее) с передачей this и других аргументов. Мы можем создать экземпляр German Shepard.
var pet = Dog("germanShepard", animalGroups.MAMMAL); console.log(pet); // returns Dog {name: "germanShepard", type: 1, sound: "bow"}
Мы не назначаем имя и тип дочерней функции, мы вызываем супер функцию Animal и устанавливаем соответствующие свойства. Домашнее животное имеет свойства (имя, тип) родителя. Но как насчет методов. Наследуются ли они тоже? Давайте посмотрим!
pet.shout(); // Throws error
Как же так? Почему это произошло? Это происходит потому, что мы не сказали JavaScript, чтобы наследовать методы родительского класса. Как это исправить?
// Link prototype chains Dog.prototype = Object.create(Animal.prototype); var pet = new Dog("germanShepard", animalGroups.MAMMAL); // Now shout method is available pet.shout(); // germanShepard is bowing...
Теперь method доступен. Мы можем проверить, что является классом данного объекта в JavaScript, используя функцию object.constructor. Давайте посмотрим, что предсавляет класс нашего питомца - pet.
pet.constructor; // returns Animal
Это расплывчато. Animal - родительский класс. Но какой именно тип pet ? Это Dog type. Это происходит из-за конструктора Dog class.
Dog.prototype.constructor = Dog;
Эти четыре вещи, которые вы должны помнить о прототипическом наследовании.
- Свойства класса связаны c this.
- Методы класса связаны с прототипом объекта Object.prototype
- Чтобы наследовать свойства, используйте функцию вызова call, передающую this объекта.
- Чтобы наследовать методы, используйте Object.create для связывания прототипов родительского и дочернего
- Всегда устанавливайте конструктор дочерних классов для получения правильного идентификатора его объектов.
Примечание. Это происходит под капотом даже с новым синтаксисом класса. Знание этих данных ценно для вашего знания JS.
В JS функция вызова - call и прототип объекта - Object.prototype обеспечивают наследование
7) Хорошо понимать обратные вызовы (callbacks) и обещания (promises)
Обратные вызовы (Callbacks)- это функции, выполняемые после выполнения операции ввода-вывода. Время, затрачиваемое на операцию ввода-вывода, может блокировать код, который не позволяет выполнять дальнейшее выполнение в Python / Ruby. Но в JavaScript из-за разрешенного асинхронного выполнения мы можем обеспечить обратные вызовы для асинхронных функций. Примером может служить вызов AJAX (XMLHttpRequest) из браузера на сервер, события, генерируемые мышью. клавиатуры и т. д. Примерfunction reqListener () { console.log(this.responseText); } var req = new XMLHttpRequest(); req.addEventListener("load", reqListener); req.open("GET", "http://www.example.org/example.txt"); req.send();
Здесь reqListener - это обратный вызов, который будет выполняться, когда запрос GET успешно возвращается.
Обещания (promises) - это аккуратные обертки для обратных вызовов, которые позволяют нам запускать асинхронный код элегантно. Я много обсуждал здесь обещания. Это также важный элемент, который должен быть известен всем в JS. Writing neat asynchronous Node JS code with Promises
8) Хорошо понимать регулярные выражения
У регулярных выражений много приложений. Обработка текста, соблюдение правил ввода данных и т. д. Разработчик JavaScript должен знать, как выполнять базовое Regex и решать проблемы. Regex - универсальная концепция. Мы здесь видим, как мы можем это сделать из JS.Мы можем создать новое регулярное выражение, используя это
var re = /ar/; var re = new RegExp('ar'); // This too works
Вышеприведенное регулярное выражение является выражением, которое соответствует заданному набору строк. Как только регулярное выражение определено, мы можем попытаться подобрать и увидеть соответствующую строку. мы можем сопоставить строки с помощью функции exec (exec function).
re.exec("car"); // returns ["ar", index: 1, input: "car"] re.exec("cab"); // returns null
Существует несколько специальных классов символов, которые позволяют нам писать сложные регулярные выражения.
В RegEx существует много типов элементов. Некоторые из них:
- Символы Ex:\ w - буквенно-цифровые, \ d - десятичные, \ D - не десятичные
- Классы символов Ex: [x-y] в диапазоне от x до y, [^ x] не x
- Квантификаторы Ex: +,?, * (Жадные и ленивые)
- Границы Ex: ^ (начало ввода), $ (конец ввода)
Используя приведенные выше вещи, давайте проиллюстрируем несколько примеров.
/* Character class */ var re1 = /[AEIOU]/; re1.exec("Oval"); // returns ["O", index: 0, input: "Oval"] re1.exec("2456"); // null var re2 = /[1-9]/; re2.exec('mp4'); // returns ["4", index: 2, input: "mp4"] /* Characters */ var re4 = /\d\D\w/; re4.exec('1232W2sdf'); // returns ["2W2", index: 3, input: "1232W2sdf"] re4.exec('W3q'); // returns null /* Boundaries */ var re5 = /^\d\D\w/; re5.exec('2W34'); // returns ["2W3", index: 0, input: "2W34"] re5.exec('W34567'); // returns null var re6 = /^[0-9]{5}-[0-9]{5}-[0-9]{5}$/; re6.exec('23451-45242-99078'); // returns ["23451-45242-99078", index: 0, input: "23451-45242-99078"] re6.exec('23451-abcd-efgh-ijkl'); // returns null /* Quantifiers */ var re7 = /\d+\D+$/; re7.exec('2abcd'); // returns ["2abcd", index: 0, input: "2abcd"] re7.exec('23'); // returns null re7.exec('2abcd3'); // returns null var re8 = /<([\w]+).*>(.*?)<\/\1>/; re8.exec('Hello JS developer
'); //returns ["Hello JS developer
", "p", "Hello JS developer", index: 0, input: "Hello JS developer
"]
Для получения дополнительной информации о регулярном выражении, пройдите по ссылке Quick-Start: Regex Cheat Sheet.
Наряду с exec существуют и другие функции, а именно match, search и, replace доступны для поиска строки в другой с использованием регулярных выражений. Но эти функции должны использоваться в строковых выражениях.
"2345-678r9".match(/[a-z A-Z]/); // returns ["r", index: 8, input: "2345-678r9"] "2345-678r9".replace(/[a-z A-Z]/, ""); // returns 2345-6789
Regex - важная тема, которую разработчики должны легко понимать для решения сложных задач.
9) Хорошо понимать Map, Reduce и Filter
Функциональное программирование - это тема обсуждения в эти дни. Многие языки программирования включают в себя функциональные концепции, такие как lambdas, в их новые версии (пример: Java> 7). В JavaScript поддержка конструкций функционального программирования существует в течение длительного времени. Есть три основные функции, которые нам нужно глубоко изучить. Математические функции принимают некоторый входной (input) и обратный вывод (return output). Чистая функция всегда возвращает тот же вывод output) для данного ввода (input). Функции, которые мы обсуждаем сейчас, также являются чистыми.map
Функция map доступна в массиве JavaScript. Используя эту функцию, мы можем получить новый массив, применив функцию преобразования для каждого элемента в массиве. Общий синтаксис для работы map массива JS:arr.map((elem){ process(elem) return processedValue }) // returns new array with each element processed
Предположим, есть несколько нежелательных символов, введенных в серийные ключи, с которыми мы работаем в последнее время. Нам нужно их удалить. Вместо удаления символа путем итерации и поиска мы можем использовать map для выполнения той же операции и получения массива результатов.
var data = ["2345-34r", "2e345-211", "543-67i4", "346-598"]; var re = /[a-z A-Z]/; var cleanedData = data.map((elem) => {return elem.replace(re, "")}); console.log(cleanedData); // ["2345-34", "2345-211", "543-674", "346-598"]
Примечание. Мы использовали стрелочный синтаксис (arrow syntax) для определения функции в JavaScript ES6
map принимает функцию в качестве аргумента. Эта функция имеет аргумент. Этот аргумент выбирается из массива. Нам нужно вернуть обработно элемент, который будет применим ко всем элементам массива.
Другими словами мы хотим выполнить определенные действия с каждым элементом массива.
reduce
Функция reduce урезает данный список до конечного результата. Мы также можем сделать то же самое, итерации массива и сохранение промежуточного результата в переменной. Но здесь это более чистый способ уменьшить массив до значения. Общий синтаксис для операции reduce JS:arr.reduce((accumulator, currentValue, currentIndex) => { process(accumulator, currentValue) return intermediateValue/finalValue }, initialAccumulatorValue) // returns reduced value
accumulator
сохраняет промежуточное и конечное значение. CurrentIndex
, currentValue
- это индекс и значение элемента из массива соответственно. initialAccumulatorValue
передает это значение в аргумент аккумулятора.
Одним из практических приложений для reduce может быть сглаживание массива массивов. Сглаживание (Flattening) преобразует внутренние массивы в один массив. Для Ex:
var arr = [[1, 2], [3, 4], [5, 6]]; var flattenedArray = [1, 2, 3, 4, 5, 6];
Мы можем добиться этого путем обычной итерации. Но, используя сокращение, это более читабельный и простой код. Магия!
var flattenedArray = arr.reduce((accumulator, currentValue) => { return accumulator.concat(currentValue); }, []); // returns [1, 2, 3, 4, 5, 6]
filter
Это третий тип концепции функционального программирования. Он близок к map, поскольку он также обрабатывает каждый элемент в массиве и, наконец, возвращает другой массив (не возвращающий значение, как в сокращении). Длина фильтрованного массива может быть меньше или равна исходному массиву. Поскольку условие фильтрации, которое мы передаем, может исключать несколько / нулевых входов в выходном массиве. Общий синтаксис для работы filter JS:arr.filter((elem) => { return true/false })
Здесь elem - это элемент данных массива, и true / false следует возвращать из функции, чтобы указать включение / исключение фильтрованного элемента. Общим примером является фильтрация массива слов, который начинается и заканчивается заданными условиями. Предположим, мы должны отфильтровать массив слов, начинающийся с t и заканчивающийся на r.
var words = ["tiger", "toast", "boat", "tumor", "track", "bridge"] var newData = words.filter((elem) => { return elem.startsWith('t') && elem.endsWith('r') ? true:false; }); // returns ["tiger", "tumor"]
Эти три функции должны быть у вас под рукой, когда кто-то спрашивает вас о функциональных аспектах программирования JavaScript. Как вы видите, исходный массив не изменяется во всех трех случаях, которые доказывают чистоту этих функций.
10) Понимать шаблоны обработки ошибок
Это самый малозанятый фрагмент JavaScript для многих разработчиков. Я вижу, что очень немногие разработчики говорят об обработке ошибок. Хороший подход к разработке всегда тщательно переносить JS-код вокруг блоков try / catch.Николас К. Закас (Nicholas C. Zakas), инженер UI в Yahoo, сказал в 2008 году: "Всегда предполагайте, что ваш код не удастся. Невозможно правильно обработать события! Запишите их на сервер. Брось свои ошибки."
В JavaScript всякий раз, когда мы кодируем, мы всегда можем потерпеть неудачу. Для Ex:
$("button").click(function(){ $.ajax({url: "user.json", success: function(result){ updateUI(result["posts"]); }}); });
Здесь мы попадаем в ловушку, говоря, что результаты всегда будут объектом JSON. Иногда сервер может сбой, и вместо результата возвращается null. В этом случае null ["posts"] выдаст ошибку. Правильное обращение может быть таким!
$("button").click(function(){ $.ajax({url: "user.json", success: function(result){ try { updateUI(result["posts"]); } catch(e) { // Custom functions logError(); flashInfoMessage(); } }}); });
Функция logError предназначена для сообщения об ошибке на сервере. Вторая функция flashInfoMessage- это функция, которая отображает удобное для пользователя сообщение типа «Сервис недоступен в настоящее время» и т. д.
Николас говорит, что каждый раз, когда вы чувствуете, что-то неожиданное произойдет, вы будете ловить ошибки. Различают фатальные и нефатальные ошибки. Вышеприведенная ошибка связана с тем, что сервер backend упал, что является фатальным. Таким образом вы должны сообщить клиенту, что по какой-то причине служба отключена. В некоторых случаях это может быть не смертельным, но лучше уведомлять об этом. Чтобы создать такой код, сначала выведите ошибку, поймайте ее с событием ошибки на уровне объекта
window
, затем сделайте вызов API для регистрации этого сообщения на сервер.
reportErrorToServer = function (error) { $.ajax({type: "POST", url: "http://api.xyz.com/report", data: error, success: function (result) {} }); } // Window error event window.addEventListener('error', function (e) { reportErrorToServer({message: e.message}) })} function mainLogic() { // Somewhere you feel like fishy throw new Error("user feeds are having fewer fields than expected..."); }
Этот код в основном выполняет три функции:
- Слушайте ошибки на уровне окна (window).
- Всякий раз, когда возникает ошибка, делает вызов API (API call).
- Записывает ошибку на сервер.
Вы также можете использовать новую функцию Boolean (ES5, ES6), чтобы проверить, действительна ли переменная, а не null (или) не определена, прежде чем продолжить.
if (Boolean(someVariable)) { // use variable now } else { throw new Error("Custom message") }
Всегда думайте, как обращаться с ошибками. Все может закончиться неудачей!
Другие вещи, чтобы знать (Hoisting, Event Bubbling)
Все вышеперечисленные концепции являются основными для разработчика JavaScript. Есть немного внутренних деталей, чтобы знать, что они могут быть действительно полезными. Вот как работает JavaScript-движок в браузере. Что такое Подъем -Hoisting и Событие Bubbling?Hoisting
Подъем - это процесс выталкивания объявленных переменных в начало программы во время ее запуска. Для Ex:doSomething(foo); // used before var foo; // declared later
Когда вы делаете что-то выше на языке сценариев, таком как Python, он выдает ошибку. Вы должны сначала определить что-то (переменную, функцию), а уже потом использовать это. Несмотря на то, что JS является языком сценариев, у него есть механизм подъема. В этом механизме, во время работы программы, во время работы с программой Java VM делает две вещи:
- Сначала сканируйте программу, соберите все объявления переменных и функций и назначьте для нее пространства памяти.
- Запустите программу сейчас, заполнив их любыми значения переменных если нет, заполните undefined
В приведенном выше фрагменте кода console.log печатает "undefined". Это потому, что в первом проходе собрана переменная foo. VM ищет любое значение, определенное для переменной foo. Этот подъем может привести ко многим ситуациям кода JavaScript, где код может вызывать ошибки в некоторых местах и использовать неопределенное значения по умолчанию, в другом. Вы должны знать подъем hosting , чтобы очистить ваш код от двусмысленности! Несколько примеров! Hoisting
Event Bubbling
Теперь рассмотрим событие (Event Bubbling)! По словам Аруна П, старшего инженера-программиста:«Event Bubbling - это два способа распространения событий в API DOM HTML, когда событие происходит в элементе внутри другого элемента, и оба элемента зарегистрировали обработчик для этого события. Режим распространения событий определяет, в каком порядке элементы получают событие ».
При барботировании событие сначала захватывается и обрабатывается самим внутренним элементом, а затем распространяется на внешние элементы. С захватом процесс идет обратным образом. Обычно мы прикрепляем событие к обработчику, используя функцию addEventListener.
addEventListener("click", handler, useCapture=false)
Третий аргумент useCapture - это ключ. Значение по умолчанию неверно. Таким образом, это будет пузырящая модель, в которой событие сначала обрабатывается самым внутренним элементом, и оно распространяется наружу, пока не достигнет родительского элемента. Если этот аргумент верен, он захватывает модель.
Для Ex: Bubbling Model
<div onClick="divHandler()"> <ul onClick="ulHandler"> <li id="foo"></li> </ul> </div> <script> function handler() { // do something here } function divHandler(){} function ulHandler(){} document.getElementById("foo").addEventListener("click", handler) </script>
Когда мы нажимаем элемент списка, порядок выполнения обработчиков подобен порядковому номеру (по умолчанию).
handler() => ulHandler() => divHandler()
На диаграмме обработчики последовательно запускаются наружу. Аналогично, модель захвата пытается инициировать события от родителя до щелчка элемента. Теперь измените эту строку в приведенном выше коде.
document.getElementById("foo").addEventListener("click", handler, true)
Порядок выполнения обработчиков будет следующим:
divHandler => ulHandler() => handler()
Вы должны понимать, что пузырь событий (event bubbling) (независимо от направления движения к родительскому элементу или к ребенку) должным образом реализует пользовательские интерфейсы (UI), чтобы избежать нежелательного поведения.
Это основные понятия JavaScript. Как я уже упоминал ранее, дополнительная информация о них, ваш опыт работы и знания, подготовка поможет вам пройти интервью с JavaScript. Всегда продолжайте учиться. Следите за последними событиями (ES6). Копайте глубже в различных аспектах JavaScript, таких как двигатель V6, тесты и т. д. Здесь представлено несколько видео ресурсов, которые научат вас многим вещам.
Рекомендации:
Inheritance in JavaScriptObject.prototype.constructor
Using XMLHttpRequest
Regular Expressions
What is event bubbling and capturing?
123-Essential-JavaScript-Interview-Question
Автор: Naren Arya, перевел Ярослав Колесников.
спасибо.я бы на все вопросы точно не ответил сразу,но где-то в подсознании знал все кроме
ОтветитьУдалитьрегулярных выражений.