JavaScript-функции, объекты и типы данных: подготовка к интервью

5
17203
Добавить в избранное

Мы собрали самые важные и популярные темы по JavaScript, которые попадаются на собеседованиях, и коротко, но емко рассказываем про JavaScript-функции, области видимости и асинхронный код.

Типы и приведение типов

В JavaScript имеется 7 встроенных типов: null, undefined , boolean, number, string, object и symbol (ES6). Все эти типы зовутся примитивами, кроме object.

Null и Undefined

Undefined – отсутствие определения объекта/переменной. Функция вернет undefined, когда возвращаемый объект не указан явно.

Null – отсутствие значения. Это значение можно присвоить переменной.

Неявное приведение типов

В этом примере строковая переменная name приводится к true.

К true будут приводится все неявно ложные значения, которые приводятся к boolean.

Явно ложные значения: «», 0, null, undefined, NaN, false.

Строки и числовое преобразование

Осторожно работайте с оператором «+», так как этот оператор работает как со строками, так и с числами, в то время, как «*», «/» и «-» – исключительно для чисел. Если применить эти операторы к строке, она будет преобразована в числовой тип.

== и ===

Многие привыкли считать, что оператор == проверяет равенство значений, а === – равенство типов и значений. На деле, это работает немного иначе.

  • == проверяет равенство с приведением типов
  • === проверяет равенство без приведения типов

Приведение может оказаться обманчивым:

Если сравнить переменные из примера, то console.log(a == b) вернет true. Так происходит потому, что строковая переменная a, приведенная к boolean будет одним из явно ложных значений (0), так же, как и b (false).

В операции с использованием оператора === console.log вернет false, так как переменная a не будет приведена к логическому типу.

Вот еще несколько примеров обманчивых сравнений:

Значения и ссылки

Составные значения всегда создают копию ссылки на назначение: объекты (в том, числе массивы) и функции.

Чтобы скопировать составное значение как значение, необходимо создать его копию. Таким образом, не будет ссылки на оригинальное значение.

Области видимости

Область видимости отсылает к исполняемому контексту. Она определяет доступность переменных и функций в коде.

Глобальная область видимости включает в себя все переменные, объявленные за пределами JavaScript-функции. В браузере глобальной областью будет объект window.

Локальная область видимости – это область внутри границ JavaScript-функции. Переменные, объявленные в этой области будут доступны внутри самой функции и из ее вложений.

Поднятие

«Движение» объявлений переменных и функций наверх соответствующей области видимости во время компиляции называется поднятием.

JavaScript-функции по умолчанию подняты: это значит, что функцию можно вызвать еще до ее объявления.

Переменные поднимаются иначе. Для var будет поднято только объявление, но не значение. let и const не будут подняты.

Выражение и объявление JavaScript-функции

Выражение функции – это «запись» JavaScript-функции в переменную, такое описание функции не будет поднято.

Объявление функции – это привычное описание тела функции с ключевого слова function. Такая функция будет исполняться в любом месте.

Переменные: var, let и const

До ES6 в JavaScript было возможно использовать только var. Переменные и функции, созданные внутри функции будут доступны только в области видимости JavaScript-функции. Переменные, объявленные в блоках типа if/for могут быть доступны в любой области видимости. Если условие или цикл объявлены в глобальной области – переменные возможно будет менять из любого участка кода.

Необъявленные переменные (без присвоения var, let или const) будут автоматически объявляться в глобальной области видимости.

Const и let не поднимаются и могут быть доступны внутри блока кода, ограниченного фигурными скобками.

Const не меняется, то есть нельзя присвоить новые значения. Но вот свойства меняться могут.

Замыкания

Замыкание – это функция и ее лексическое окружение. Замыкания позволяют функции иметь доступ к переменным из вложенных областей видимости – окружения.

Одно из основных преимуществ  замыканий – инкапсуляция данных. Это означает, что данные не могут быть доступны открыто, как в примере ниже.

С момента создания elementary внешняя функция была возвращена. Таким образом, переменная staff существует только внутри замыкания и не доступна ниоткуда больше.

Мгновенно выполняемые функции (Immediate Invoked Function Expression – IIFE)

IIFE – означает функцию, которая будет выполнена сразу после объявления.

  • (Окружающие скобки) препятствуют рассмотрению описываемой IIFE-функции в качестве объявления обычной.
  • Завершающие скобки() – исполняющее выражение.

При использовании IIFE:

  • Можно вкладывать закрытые данные в функцию.
  • Обновить окружение.
  • Избежать использования глобального пространства имен.

Контекст

Не путайте контекст и область видимости. Контекст определяет как функция была вызвана. К примеру, внутри контекста вызванной функции к ней можно обращаться через this. Область видимости определяет видимость переменных.

Вызов функций: call, apply и bind

Три этих метода используются, чтобы прикрепить контекст this к функции и различаются методами вызова функции.

  • .call() вызывает функцию немедленно и требует предоставить аргументы списком (один за одним).
  • .apply() вызывает функцию немедленно и позволяет передать аргументы массивом.

call() и apply() практически одинаковы и используются для вызова метода объекта. Выбор конкретного способа определяется методом передачи аргументов.

  • .bind() вернет новую функцию с точным контекстом и параметрами. Обычно это требуется для вызова функции в определенный момент и с определенном контексте. Этот метод требует передавать аргументы по одному, через запятую.

Ключевое слово this

Значение this обычно определяется контекстом выполнения функции. Контекст выполнения обычно подразумевает как функция была вызвана.

Ниже приведен список значений this, которые могут быть в зависимости от контекста.

  • Привязка через new: здесь this будет относиться к созданному объекту.

  • Явное привязывание: при вызове call или apply this будет означать объект, отправленный в качестве аргумента.
  • Обратите внимание: .bind() работает немного иначе. Метод создает новую функцию, которая вызывает оригинальную с привязанным к ней объектом.

  • Неявное привязывание: когда функция вызывается с контекстом, this будет являться объектом, методом которого является эта функция.

  • Привязка по умолчанию: если ни один из вышеперечисленных случаев не подходит, this будет являться глобальным объектом (в браузере – объект window). Функция, не являющаяся методом автоматически становится глобальным объектом.

  • Лексическое this: когда функция вызвана с помощью стрелочной функции =>, this получит значение окружающей области видимости во время создания.

Strict Mode

JavaScript будет исполняться в «строгом» режиме при использовании директивы “use strict”.

Преимущества Strict Mode:

  • Отладка становится проще – ошибки, которые в другом случае будут проигнорированы в этом режиме будут показаны.
  • Предотвращаются случайные глобальные переменные – присвоение значения к необъявленной переменной будет возвращать ошибку.
  • Препятствует недопустимому использованию удаления – попытки удалить переменные, функции и неудаляемые свойства приведут к ошибке.
  • Предотвращается дублирование имен свойств и значений параметров – это вызовет ошибку (справедливо до ES6).
  • Использовать eval() теперь безопасней – переменные и функции, объявленные в eval не будут создаваться в локальной области видимости.
  • Передача в качестве значения this null или undefined не повлияет на глобальный объект.

Ключевое слово new

Функции, вызванные с помощью new, являются функциями-конструкторами. Последовательность действий при вызове функции через new:

  1. Создается новый объект
  2. Прототип объекта устанавливается как прототип функции-конструктора.
  3. Функция-конструктор исполняется с this, как новый объект.
  4. Возвращается созданный объект.

Прототипы и наследование

В JavaScript каждый объект имеет прототип, доступный через метод .__proto__.

Прототипы реализуют в JS механизм наследования.

Цепочка прототипов

Прототипы могут образовывать цепочки наследования, каждый из объектов которого будет иметь свойства предыдущего (родительского), вплоть до первого звена.

Асинхронный JavaScript

JavaScript является однопоточным языком программирования. Главный недостаток однопоточности заключается в том, что при исполнении части кода, которая занимает много времени, весь остальной код будет выполнен с задержкой.

Каждая функция в JavaScript будет выполняться в порядке очереди в стеке вызовов: первая зашедшая в стек функция будет выполнена последней, а последняя – первой.

Решением проблемы однопоточности и очередей является использование функций обратного вызова. Асинхронный процесс начинается с размещения асинхронной функции вызова в области памяти. Эту область будем считать менеджером событий.

Цикл событий обрабатывает выполнение множества частей кода с течением времени. Он  наблюдает за стеком вызовов и очередью вызовов.

Рассмотрим код ниже, чтобы понять как это работает:

  1. При инициализации браузерная консоль, стек вызовов и менеджер событий пусты.
  2. first() добавлена в стек вызовов.
  3. console.log(«First message») добавлена в стек вызовов.
  4. console.log(«First message») выполнена и выведена в консоль.
  5. console.log(«First message») удалена из стека.
  6. first() удалена из стека.
  7. setTimeout(second, 0) добавлена в стек
  8. setTimeout(second, 0) выполнена и обработана менеджером событий. После 0ms менеджер событий переместит second() в очередь вызовов.
  9. setTimeout(second, 0) выполнена и удалена из стека.
  10. third() добавлена в стек.
  11. console.log(«Third message») добавлена в стек.
  12. console.log(«Third message») выполнена, результат выведен в консоль.
  13. console.log(«Third message») удалена из стека.
  14. third() удалена из стека.
  15. Сейчас стек вызовов пуст и функция second() ждет своей очереди для попадания в стек.
  16. Цикл событий перемещает second() из очереди событий в стек.
  17. console.log(«Second message») добавляется в стек.
  18. console.log(«Second message») выполняется и выводит сообщение в консоль.
  19. console.log(«Second message») удаляется из стека.
  20. second() удаляется из стека.
Интересуетесь веб-разработкой?

Подпишитесь на нашу рассылку, чтобы получать больше интересных материалов:

И не беспокойтесь, мы тоже не любим спам. Отписаться можно в любое время.




5 Комментарии

  1. В разделе про == и === ошибка.

    let a = ‘0’;
    let b = false;
    console.log(a == b) вернёт true, но преобразование не к Boolean будет, а к Number.
    При сравнивании через == данных различных типов используется численное преобразование. И ‘0’ преобразуется в 0, и false в 0, потому и true. А если предположим было бы как по вашему преобразование к Boolean, то строка ‘0’ как непустая будет true и потом a == b уже не будет true т.к. b — false.

  2. Цитата: «Const и let неизменяемые, то есть им нельзя присвоить новые значения. Но они могут менять свои свойства.»

    У вас в предыдущем же примере let перезаписывается. Исправьте.

Оставьте комментарий