Что означает директива use strict
Строгий режим — «use strict»
На протяжении долгого времени JavaScript развивался без проблем с обратной совместимостью. Новые функции добавлялись в язык, в то время как старая функциональность не менялась.
Преимуществом данного подхода было то, что существующий код продолжал работать. А недостатком – что любая ошибка или несовершенное решение, принятое создателями JavaScript, застревали в языке навсегда.
«use strict»
Позже мы изучим функции (способ группировки команд). Забегая вперёд, заметим, что вместо всего скрипта «use strict» можно поставить в начале большинства видов функций. Это позволяет включить строгий режим только в конкретной функции. Но обычно люди используют его для всего файла.
Проверьте, что «use strict» находится в первой исполняемой строке скрипта, иначе строгий режим может не включиться.
Здесь строгий режим не включён:
Над «use strict» могут быть записаны только комментарии.
Как только мы входим в строгий режим, отменить это невозможно.
Консоль браузера
В дальнейшем, когда вы будете использовать консоль браузера для тестирования функций, обратите внимание, что use strict по умолчанию в ней выключен.
Иногда, когда use strict имеет значение, вы можете получить неправильные результаты.
Можно использовать Shift + Enter для ввода нескольких строк и написать в верхней строке use strict :
В большинстве браузеров, включая Chrome и Firefox, это работает.
Всегда ли нужно использовать «use strict»?
Вопрос кажется риторическим, но это не так.
Кто-то посоветует начинать каждый скрипт с «use strict» … Но есть способ покруче.
Подытожим: пока очень желательно добавлять «use strict»; в начале ваших скриптов. Позже, когда весь ваш код будет состоять из классов и модулей, директиву можно будет опускать.
Пока мы узнали о use strict только в общих чертах.
В следующих главах, по мере расширения знаний о возможностях языка, мы яснее увидим отличия между строгим и стандартным режимом. К счастью, их не так много, и все они делают жизнь разработчика лучше.
Все примеры в этом учебнике подразумевают исполнение в строгом режиме, за исключением случаев (очень редких), когда оговорено иное.
Зачем в JavaScript нужен строгий режим?
Строгий режим (strict mode) — это важная часть современного JavaScript. Именно этот режим позволяет разработчикам пользоваться более ограниченным, чем стандартный, синтаксисом.
Семантика строгого режима отличается от традиционного нестрогого режима, который иногда называют «грязным» (sloppy mode). В таком режиме синтаксические правила языка не так строги, а когда происходят некоторые ошибки, система никак не оповещает о них пользователя. То есть — ошибки могут быть проигнорированы, а код, в котором они допущены, сможет выполняться дальше. Это способно привести к неожиданным результатам выполнения кода.
Строгий режим вносит в семантику JavaScript некоторые изменения. Он не даёт системе закрывать глаза на ошибки, выдавая соответствующие исключения. Это приводит к остановке выполнения программ.
Строгий режим, кроме того, помогает в написании программ, в которых нет недочётов, мешающих JS-движкам оптимизировать код. Далее, в этом режиме запрещено использование элементов синтаксиса, которые могут получить особый смысл в будущих версиях языка.
Особенности применения строгого режима
Если в проекте имеются некоторые скрипты, в которых не используется строгий режим, и другие, в которых этот режим используется, тогда может случиться так, что эти скрипты окажутся объединены.
Это приведёт к тому, что код, который не предназначен для выполнения в строгом режиме, окажется в таком состоянии, когда система попытается выполнить его в строгом режиме. Возможно и обратное — код, написанный для строгого режима, попадёт в нестрогий режим. Поэтому лучше всего не смешивать «строгие» и «нестрогие» скрипты.
Как уже было сказано, строгий режим можно применять к отдельным функциям. Для того чтобы это сделать — конструкцию «use strict» или ‘use strict’ надо поместить в верхнюю часть тела функции, до любых других команд. Строгий режим при таком подходе применяется ко всему, что размещено в теле функции, включая вложенные функции.
В JavaScript-модулях, которые появились в стандарте ES2015, строгий режим включён по умолчанию. Поэтому при работе с ними включать его явным образом не нужно.
Изменения, вводимые в работу JS-кода строгим режимом
▍Преобразование «тихих» ошибок в исключения
«Тихие» ошибки преобразуются в строгом режиме в исключения. В нестрогом режиме на такие ошибки система явным образом не реагирует. В строгом же режиме наличие таких ошибок приводит к неработоспособности кода.
Попытка выполнения любого кода, который, в обычном режиме, просто не работает, теперь приводит к выдаче исключения. В виде ошибок рассматриваются любые неправильные синтаксические конструкции, которые в нестрогом режиме просто игнорировались.
В строгом режиме исключение, например, будет выдано в следующих случаях:
К выдаче TypeError приведёт и попытка удаления неудаляемого свойства:
Строгий режим запрещает назначать объекту свойства с одинаковыми именами. Как результат — попытка выполнения следующего кода приведёт к возникновению синтаксической ошибки:
В строгом режиме запрещены параметры функций с одинаковыми именами. В результате попытка выполнения следующего кода приведёт к возникновению синтаксической ошибки:
В строгом режиме нельзя использовать восьмеричную запись чисел, предваряя число нулём. Этого нет в спецификации, но данная возможность поддерживается браузерами.
Такое положение дел путает разработчиков, заставляя их полагать, что 0, предшествующий числу, просто игнорируется, не имея особого смысла. В строгом режиме попытка воспользоваться числом, в начале которого стоит 0, приведёт к синтаксической ошибке.
Строгий режим, кроме того, запрещает использование конструкций, затрудняющих оптимизацию. Интерпретатору, перед выполнением оптимизации кода, нужно знать о том, что переменная хранится именно там, где, как считает интерпретатор, она хранится. В строгом режиме запрещается то, что мешает оптимизациям.
Предположим, есть такой код:
Результатом этой попытки будет синтаксическая ошибка.
Строгий режим, кроме того, запрещает удаление обычных переменных. В результате попытка выполнить следующий код приведёт к синтаксической ошибке:
▍Запрет некорректных синтаксических конструкций
Вот примеры некорректного использования eval и arguments :
В строгом режиме нельзя создавать псевдонимы для объекта arguments и устанавливать новые значения arguments через эти псевдонимы.
Предположим, имеется следующий код:
▍Оптимизации производительности
▍Изменения, имеющие отношение к безопасности
Эти возможности представляют собой потенциальную угрозу безопасности. В результате в строгом режиме доступ к этим свойствам запрещён.
В ES2015 и в более поздних версиях стандарта эти идентификаторы стали зарезервированными словами. И их нельзя использовать для именования переменных или свойств в строгом режиме.
Итоги
Строгий режим — это стандарт, который существует уже многие годы. Он пользуется чрезвычайно широкой поддержкой браузеров. Проблемы с кодом, выполняемом в строгом режиме, могут возникать лишь у старых браузеров, таких, как Internet Explorer.
У современных браузеров не должно возникать сложностей со строгим режимом JavaScript. В результате можно сказать, что этот режим стоит использовать ради предотвращения «тихих» ошибок и ради повышения безопасности приложений. «Тихие» ошибки преобразуются в исключения, препятствующие выполнению программ, а в плане повышения безопасности можно, например, отметить механизмы строгого режима, ограничивающие eval и предотвращающие доступ к стеку вызовов функций. Кроме того, использование строгого режима облегчает оптимизацию кода JS-движками и заставляет программиста осторожно обращаться с зарезервированными словами, которые могут найти применение в будущих версиях JavaScript.
Уважаемые читатели! Пользуетесь ли вы строгим режимом при написании JS-кода своих проектов?
Strict mode
Режим strict (строгий режим), введённый в ECMAScript 5, позволяет использовать более строгий вариант JavaScript. Это не просто подмножество языка: в нем сознательно используется семантика, отличающаяся от обычно принятой. Не поддерживающие строгий режим браузеры будут по-другому выполнять код, написанный для строгого режима, поэтому не полагайтесь на строгий режим без тестирования поддержки используемых особенностей этого режима. Строгий и обычный режим могут сосуществовать одновременно, а скрипт может переключаться в строгий режим по мере надобности.
Активизация строгого режима
Строгий режим для скриптов
Чтобы активизировать строгий режим для всего скрипта, нужно поместить оператор «use strict»; или ‘use strict’; перед всеми остальными операторами скрипта (выдержать приведённый синтаксис буквально).
В этой синтаксической конструкции кроется ловушка, в которую уже угодили даже самые известные сайты: нельзя бездумно объединять скрипты с разными режимами. Объединение скрипта в строгом режиме со скриптом в обычном выглядит как скрипт в строгом режиме! Справедливо и обратное: объединение обычного скрипта со строгим выглядит как нестрогий скрипт. Объединение только строгих или только обычных скриптов проходит без последствий, проблему вызывает совместное использование скриптов со строгим и обычным режимом. Поэтому рекомендуется включать строгий режим только на уровне функций (хотя бы в течение переходного периода).
Вы также можете использовать подход «обёртывания» всего содержимого скрипта в функцию, для которой включён строгий режим. Это уменьшит возможность возникновения проблем при объединении скриптов, но одновременно потребует явно экспортировать из контекста функции все глобальные переменные.
Строгий режим для функций
Аналогично, чтобы включить строгий режим для функции, поместите оператор «use strict»; (или ‘use strict’; ) в тело функции перед любыми другими операторами.
Строгий режим для модулей
ECMAScript 2015 представил модули JavaScript и, следовательно, 3-й способ войти в строгий режим. Все содержимое модулей JavaScript автоматически находится в строгом режиме, и для его запуска не требуется никаких инструкций.
Изменения в строгом режиме
Строгий режим изменяет синтаксис и поведение среды исполнения. Изменения главным образом попадают в следующие категории: преобразование ошибок в исключения; изменения, упрощающие вычисление переменной в определённых случаях использования её имени; изменения, упрощающие eval и arguments ; изменения, упрощающие написание «безопасного» JavaScript, и изменения, предвосхищающие дальнейшее развитие ECMAScript.
Преобразование ошибок в исключения
Строгий режим превращает некоторые прощавшиеся ранее ошибки в исключения. JavaScript был разработан с расчётом на низкий порог вхождения, и временами он придаёт заведомо ошибочным операциям семантику нормального кода. Иногда это помогает срочно решить проблему, а иногда это создаёт худшие проблемы в будущем. Строгий режим расценивает такие ошибки как ошибки времени выполнения, для того чтобы они могли быть обнаружены и исправлены в обязательном порядке.
Во-первых, строгий режим делает невозможным случайное создание глобальных переменных. В обычном JavaScript опечатка в имени переменной во время присваивания приводит к созданию нового свойства глобального объекта, и выполнение продолжается (хотя в современном JavaScript оно, вероятно, аварийно завершится в дальнейшем). Присваивания, которые могут случайно создать глобальную переменную, в строгом режиме выбрасывают исключение:
В-третьих, в строгом режиме попытки удалить неудаляемые свойства будут вызывать исключения (в то время как прежде такая попытка просто не имела бы эффекта):
Это уже не является проблемой в ECMAScript 2015 (баг 1041128).
Упрощение работы с переменными
Строгий режим упрощает сопоставление имени переменной с местом её определения в коде. Многие оптимизации времени компиляции полагаются на возможность считать, что переменная X хранится в этом конкретном месте исходного кода. Иногда, при компиляции JavaScript простое сопоставление имени переменной с местом её определения в коде не возможно, без выполнения того самого кода. Строгий же режим исключает большинство таких случаев, благодаря чему оптимизации компилятора работают эффективнее.
В-третьих, строгий режим запрещает удаление простых имён. delete name в строгом режиме является синтаксической ошибкой:
Упрощение eval и arguments
Во-первых, ключевые слова eval и arguments не могут быть переопределены или изменены. Все подобные попытки это сделать являются синтаксическими ошибками:
«Безопасный» JavaScript
Строгий режим упрощает написание «безопасного» JavaScript-кода. Сейчас некоторые веб-сайты предоставляют пользователям возможность писать JavaScript, который будет выполняться на сайте от имени других пользователей. В браузерах, JavaScript может иметь доступ к приватной информации пользователя, поэтому, в целях ограничения доступа к запретной функциональности, такой JavaScript перед выполнением должен быть частично преобразован. Гибкость JavaScript делает это практически невозможным без многочисленных проверок во время исполнения. Функционал, исполняемый языком иногда столь массивен, что выполнение любых дополнительных проверок во время исполнения скрипта приведёт к значительной потере производительности. Однако, некоторые особенности строгого режима, плюс обязательное требование того, чтобы JavaScript, загруженный пользователем, имел строгий режим и вызывался определённым способом, существенно снижают потребность в таких проверках.
В-третьих, в функциях строгого режима свойство arguments больше не предоставляет доступ к переменным, созданным внутри функции. В некоторых предыдущих реализациях ECMAScript arguments.caller представлял собой объект, свойства которого являлись ссылками на переменные, созданные внутри функции при её вызове. Это представляет собой угрозу безопасности, так как нарушает возможность скрывать приватные данные внутри функций (замыканий). Также это делает невозможными большинство оптимизаций. Исходя из этих причин, ни один из современных браузеров не реализует этого поведения. Но всё же, ввиду своей исторической функциональности, arguments.caller для функций в строгом режиме всё ещё является неудаляемым свойством, которое вызывает исключение при попытке его чтения или записи:
Подготовка почвы для будущих версий ECMAScript
В будущих версиях ECMAScript с высокой вероятностью появится новый синтаксис, и для упрощения перехода на новые версии, в строгом режиме ECMAScript 5 введено несколько ограничений. Всегда проще вносить изменения в стандарт, если заранее подготовить для них основу в строгом режиме.
Во-вторых, в строгом режиме запрещается объявление функций глубже самого верхнего уровня скрипта или функции. В обычном коде в браузерах, объявление функций позволено «везде», что не является частью ES5 (или даже ES3!) Это расширение различных браузеров, не имеющее общего совместимого подхода. Есть надежда, что в последующих редакциях ECMAScript будет определена новая семантика для объявления функций вне верхнего уровня скрипта или функции. Запрет на объявление таких функций в строгом режиме производит «зачистку» для спецификации в будущем релизе ECMAScript:
Данный запрет не является особенностью строгого режима, потому что такое объявление функций является одним из расширений основного ES5. Но это рекомендация комитета ECMAScript, и браузеры реализуют её.
Строгий режим в браузерах
В большинстве браузеров в настоящее время строгий режим реализован. Однако не стоит впадать в слепую зависимость от него, потому что существует множество Версий браузеров, поддерживающих строгий режим лишь частично или вовсе не поддерживающих оный (например, Internet Explorer ниже версии 10!). Строгий режим изменяет семантику. Надежда на эти изменения приведёт к ошибкам и погрешностям в браузерах, в которых строгий режим не реализован. Проявляйте осторожность при использовании строгого режима, и подкрепляйте надёжность строгого режима тестами особенностей, которые проверяют, насколько верно реализованы его фрагменты. Наконец, старайтесь тестировать свой код в браузерах, как поддерживающих, так и не поддерживающих строгий режим. Если вы проводите тестирование только в тех браузерах, которые не поддерживают строгий режим, то вполне вероятно у вас появятся проблемы в браузерах, его поддерживающих, и наоборот.
Руководство по JavaScript, часть 7: строгий режим, ключевое слово this, события, модули, математические вычисления
Сегодня, в седьмой части перевода руководства по JavaScript, мы поговорим о выполнении кода в строгом режиме, об особенностях ключевого слова this, о событиях, о модулях, о математических вычислениях. Здесь же мы затронем темы работы с таймерами и асинхронного программирования.
Строгий режим
Строгий режим (strict mode) появился в стандарте ES5. В этом режиме меняется семантика языка, он нацелен на то, чтобы улучшить поведение JavaScript, что приводит к тому, что код в этом режиме ведёт себя не так, как обычный. Фактически, речь идёт о том, что в этом режиме устраняются недостатки, неоднозначности языка, устаревшие возможности, которые сохраняются в нём из соображений совместимости.
▍Включение строгого режима
Для того чтобы использовать в некоем коде строгий режим, его нужно явным образом включить. То есть, речь не идёт о том, что этот режим применяется по умолчанию. Такой подход нарушил бы работу бесчисленного количества существующих программ, опирающихся на механизмы языка, присутствовавшие в нём с самого начала, с 1996 года. На самом деле, значительные усилия тех, кто разрабатывает стандарты JavaScript, направлены именно на обеспечение совместимости, на то, чтобы код, написанный в расчёте на старые версии стандартов, можно было бы выполнять на сегодняшних JS-движках. Такой подход можно считать одним из залогов успеха JavaScript как языка для веб-разработки.
Для того чтобы включить строгий режим, используется особая директива, которая выглядит так.
Строгий режим может быть включён и на уровне отдельной функции. Для этого соответствующую директиву надо поместить в начале кода тела функции.
Подобное может оказаться полезным в том случае, если строгий режим нужно использовать в существующей кодовой базе и при этом включение его на уровне файла оказывается нецелесообразным по причине нехватки времени на тщательное тестирование кода всего этого файла.
Надо отметить, что, если строгий режим включён, выключить его во время выполнения программы нельзя.
Рассмотрим некоторые особенности строгого режима.
▍Борьба со случайной инициализацией глобальных переменных
Мы уже говорили о том, что если случайно назначить некое значение необъявленной переменной, даже если сделать это в коде функции, такая переменная по умолчанию будет сделана глобальной (принадлежащей глобальному объекту). Это может привести к неожиданностям.
Например, следующий код приводит к созданию именно такой переменной.
Переменная variable будет доступна в глобальной области видимости после выполнения IIFE.
Если включить на уровне этой функции строгий режим, тот же самый код вызовет ошибку.
▍Ошибки, возникающие при выполнении операций присваивания значений
JavaScript, в обычном режиме, никак не сообщает о некоторых ошибках, возникающих в ходе выполнения операций присваивания значений.
В JavaScript можно задавать свойства объектов с использованием метода Object.defineProperty(). В частности, с помощью этого метода можно задавать свойства, которые нельзя менять.
То же самое относится и к геттерам. Этот код выполнится, хотя и безрезультатно.
А попытка выполнить то же самое в строгом режиме вызовет ошибку, сообщающая о попытке установки свойства объекта, у которого есть лишь геттер.
В JavaScript есть метод Object.preventExtensions(), делающий объект нерасширяемым, то есть таким, к которому нельзя добавить новые свойства. При работе с такими объектами в обычном режиме проявляются те же особенности языка, которые мы рассматривали выше.
В эту же категорию действий, не приводящих к каким-то изменениям, возможно, ожидаемым программистом, но и не вызывающих ошибок, попадают операции, в ходе выполнения которых делаются попытки назначить некие свойства примитивным значениям. Например, такой код, в обычном режиме, не вызовет ошибки, но и не даст никаких результатов.
▍Ошибки, связанные с удалением сущностей
В обычном режиме, если попытаться удалить, помощью оператора delete, свойство объекта, которое удалить нельзя, delete просто возвратит false и всё тихо закончится неудачей.
В строгом режиме здесь будет выдана ошибка.
▍Аргументы функций с одинаковыми именами
Функции могут иметь параметры с одинаковыми именами, ошибок это не вызывает (хотя подобное выглядит как ошибка того, кто такую функцию создал).
Кстати, если при объявлении стрелочной функции её параметры будут иметь одинаковые имена, это, и в обычном режиме, приведёт к выводу сообщения об ошибке.
▍Восьмеричные значения
▍Оператор with
Особенности ключевого слова this
▍Ключевое слово this в строгом режиме
▍Ключевое слово this в методах объектов
Метод — это функция, ссылка на которую записана в свойство объекта. Ключевое слово this в такой функции ссылается на этот объект. Это утверждение можно проиллюстрировать следующим примером.
Обратите внимание на то, что вышеприведённый способ объявления метода объекта аналогичен такому:
То же самое поведение ключевого слова this в методе объекта можно наблюдать и при использовании следующей конструкции.
▍Ключевое слово this и стрелочные функции
Попробуем переписать вышеприведённый пример с использованием, в качестве метода объекта, стрелочной функции.
▍Привязка this
▍О привязке this в обработчиках событий браузера
События
JavaScript в браузере использует событийную модель программирования. Те или иные действия выполняются кодом в ответ на происходящие события. В этом разделе мы поговорим о событиях и о том, как их обрабатывать.
В качестве события может выступать, например, завершение загрузки DOM, получение данных, выполненное в результате асинхронного запроса, щелчок мышью по элементу страницы, прокрутка страницы, ввод некоего символа с клавиатуры. На самом деле, существует множество событий, обрабатывая которые, JS-код страницы позволяет решать широкий спектр задач по взаимодействию приложения с пользователями, с элементами страницы, с окружением, в котором работает код.
▍Обработчики событий
Реагировать на события можно с помощью обработчиков событий (event handler), которые представляют собой функции, вызываемые в тот момент, когда происходят события.
При необходимости для обработки одного и того же события можно зарегистрировать несколько обработчиков, которые будут вызываться в том случае, если это событие произойдёт. Регистрировать обработчики событий можно различными способами. Рассмотрим три таких способа.
▍Встроенные обработчики событий
В HTML-коде кнопки Button 2 применяется похожий подход, но здесь указывается функция, код которой выполняется в ответ на нажатие кнопки. Этот код выполняет вывод заданной строки в консоль и выводит окно с тем же текстом.
▍Назначение обработчика свойству HTML-элемента
Этот метод назначения обработчиков событий подходит для случаев, когда у некоего события элемента должен быть лишь один обработчик. Заключается он в назначении функции соответствующему свойству элемента.
Проверить, назначен ли обработчик некоему событию, можно так.
▍Использование метода addEventListener()
▍О назначении обработчиков событий различным элементам
▍Объект Event
В этом же примере, для обработки событий, связанных с мышью, используется объект MouseEvent. В обработчике события mousedown мы выводим в консоль тип события, номер кнопки (свойство button ) и координаты указателя в момент щелчка (свойства clientX и clientY ).
Объект DragEvent применяется при обработке событий, возникающих при перетаскивании элементов страницы.
▍Всплытие событий
Рассмотрим следующий пример.
Если открыть загрузить страницу с таким кодом в браузер, открыть консоль и последовательно щёлкнуть мышью сначала в свободной области страницы, потом — по синему прямоугольнику, а потом — по зелёному, то в консоль попадёт следующее:
То, что здесь можно наблюдать, называется всплытием события (event bubbling). А именно, событие, возникающее у дочернего элемента, распространяется на родительский элемент. Этот процесс продолжается до тех пор, пока событие не достигнет самого «верхнего» элемента. Если у элементов, по которым проходит всплывающее событие, определены соответствующие обработчики, они будут вызваны в соответствии с порядком распространения события.
▍Часто используемые события
Рассмотрим некоторые события, обработка которых нужна чаще всего.
Событие load
События мыши
События клавиатуры
Событие scroll
Ограничение частоты выполнения вычислений в обработчиках событий
События mousemove и scroll дают сведения о координатах мыши и о позиции прокрутки. Выполнение в обработчиках таких событий каких-то серьёзных вычислений может привести к замедлению работы программы. В подобной ситуации есть смысл задуматься об ограничении частоты выполнения таких вычислений. Этот приём называют «троттлингом» (throttling), его реализации можно найти в специализированных библиотеках вроде Lodash. Сущность этого приёма заключается в создании механизма, который позволяет ограничить частоту выполнения неких действий, которые, без ограничения, выполнялись бы слишком часто. Рассмотрим собственную реализацию этого механизма.
ES-модули
В стандарте ES6 появилась новая возможность, получившая название ES-модули. Потребность в стандартизации этой возможности назрела уже давно, что выражается в том, что и разработчики клиентских частей веб-проектов, и серверные программисты, пишущие для среды Node.js, уже давно нечто подобное используют.
Модуль представляет собой файл, содержащий некий код. Из этого файла можно экспортировать, делать общедоступными, функции и переменные. Ими можно воспользоваться, просто подключив модуль к некоему файлу с кодом, при этом внутренние механизмы модуля извне недоступны.
В Node.js в качестве системы модулей долгое время использовался и продолжает использоваться стандарт CommonJS. В браузерах, до появления ES-модулей, применялись различные библиотеки и системы сборки проектов, имитирующие возможность работы с модулями. Теперь же, после стандартизации, браузеры постепенно вводят поддержку ES-модулей, что позволяет говорить о том, что, для поддержки модулей, уже довольно скоро дополнительных средств не понадобится. В частности, по информации ресурса caniuse.com, в конце ноября 2018 года уровень поддержки ES-модулей браузерами немного превышает 80%.
Работа по внедрению ES-модулей ведётся и в Node.js.
▍Синтаксис ES-модулей
В Node.js для подключения ES-модулей применяется такая запись.
При работе с CommonJS-модулями то же самое выглядит так.
Здесь в модуле задана команда экспорта по умолчанию, поэтому экспортироваться может анонимная функция. В противном случае экспортируемым сущностям надо давать имена.
Теперь этот модуль можно импортировать в некий код (в другой модуль, например) и воспользоваться там его возможностями.
Загрузить модуль на HTML-страницу можно, используя тег
Обратите внимание на то, что такой способ импорта модулей работает как отложенная (defer) загрузка скрипта. Кроме того, важно учитывать то, что в нашем примере в модуле uppercase.js используется экспорт по умолчанию, поэтому, при его импорте, ему можно назначить любое желаемое имя. Вот как это выглядит в коде веб-страницы. Для того чтобы у вас этот пример заработал, вам понадобится локальный веб-сервер. Например, если вы пользуетесь редактором VSCode, можно воспользоваться его расширением Live Server (идентификатор — ritwickdey.liveserver).
Модули можно импортировать и с использованием абсолютного URL.
▍Другие возможности импорта и экспорта
Выше мы приводили пример модуля, использующего экспорт по умолчанию.
Однако из модуля можно экспортировать и несколько сущностей.
Импортировать из модуля можно только то, что нужно, пользуясь конструкциями следующего вида.
Пользоваться тем, что импортировано, можно напрямую.
Импортируемые сущности можно переименовывать:
Вот как его импортировать и использовать.
Пример работы с модулем можно посмотреть здесь.
При загрузке модулей используется CORS. Это означает, что для успешной загрузки модулей с других доменов у них должен быть задан заголовок CORS, разрешающий межсайтовую загрузку скриптов (наподобие Access-Control-Allow-Origin: * ).
▍Атрибут nomodule
▍О модулях ES6 и WebPack
Модули ES6 — это замечательная технология, привлекающая тем, что она входит в стандарт ECMAScript. Но, пользуясь модулями, нужно стремиться к тому, чтобы количество загружаемых файлов было бы небольшим, иначе это может сказаться на производительности загрузки страницы. В этой связи стоит сказать, что бандлер WebPack, используемый для упаковки кода приложений, по видимому, ещё долго не потеряет актуальности.
▍Модули CommonJS
Как уже было сказано, в Node.js используется система модулей CommonJS. Эта система позволяет разработчику создавать небольшие самостоятельные фрагменты кода, подходящие для использования во множестве проектов и поддающиеся автономному тестированию. На основе CommonJS создана огромнейшая экосистема модулей npm.
Давайте напишем CommonJS-модуль, основываясь на примере, который мы уже рассматривали. А именно, поместим в файл up-node.js следующий код.
Для того чтобы воспользоваться этим модулем в некоей программе, его нужно подключить.
Обычно пакеты, загружаемые из npm, импортируют так, как показано ниже.
Модули CommonJS загружаются синхронно и обрабатываются в том порядке, в котором осуществляется обнаружение в коде соответствующих команд. Эта система не используется в клиентском коде.
Из CommonJS-модуля можно экспортировать несколько сущностей.
Импортировать их можно следующим образом, используя возможности по деструктурирующему присваиванию.
Математические вычисления
▍Арифметические операторы
Сложение (+)
Оператор + выполняет сложение чисел и конкатенацию строк. Вот примеры его использования с числами:
Вот как он ведёт себя со строками, преобразуя, при необходимости, другие типы данных к строковому типу.
Вычитание (-)
Деление (/)
При работе с обычными числами оператор деления ведёт себя вполне ожидаемым образом.
Остаток от деления (%)
Оператор % возвращает остаток от деления, в некоторых ситуациях это может оказаться полезным.
Остатком от деления на 0 является особое значение NaN (Not a Number — не число).
Умножение (*)
Возведение в степень (**)
Этот оператор возводит первый операнд в степень, заданную вторым операндом.
▍Унарные операторы
Инкремент (++)
Унарный оператор ++ можно использовать для прибавления 1 к некоему значению. Его можно размещать до инкрементируемого значения или после него.
Если же поставить его после переменной — то он сначала вернёт её предыдущее значение, а потом уже увеличит.
Декремент (—)
Унарный оператор (-)
Такой оператор позволяет делать положительные числа отрицательными и наоборот.
Унарный оператор (+)
Этот оператор, если операнд не является числом, пытается преобразовать его к числу. Если оператор уже является числом — ничего не происходит.
▍Оператор присваивания и его разновидности
Его можно прочитать так: «Прибавить к значению переменной, расположенной слева, то, что находится справа, и записать результат сложения в ту же переменную». Фактически, вышеприведённый пример можно переписать следующим образом.
По такому же принципу работают и другие подобные операторы:
▍Приоритет операторов
При работе со сложными выражениями нужно учитывать приоритет операторов. Например, рассмотрим следующее выражение.
Для переопределения порядка выполнения операторов соответствующие части выражения можно включить в круглые скобки. Рассмотрим следующее выражение.
▍Объект Math
Объект Math содержит свойства и методы, предназначенные для упрощения математических вычислений. Подробности о нём можно почитать здесь. Этот объект используется самостоятельно, без создания экземпляров.
Среди его свойств можно, например, отметить Math.E — константу, содержащую число e, и Math.PI — константу, содержащую число π.
Вот список некоторых полезных методов этого объекта.
▍Сравнение значений
Для сравнения значений в JavaScript используются операторы сравнения, с некоторыми из которых мы уже встречались.
Таймеры и асинхронное программирование
В соответствующих разделах руководства, перевод которого мы публикуем, поднимаются темы использования таймеров и асинхронного программирования. Эти темы были рассмотрены в ранее опубликованном нами переводе курса по Node.js. Для того чтобы с ними ознакомиться, рекомендуем почитать следующие материалы:
Итоги
В этом материале мы поговорили о строгом режиме, об особенностях ключевого слова this, о событиях, о модулях, о математических вычислениях. В следующий раз обсудим новшества, которые принёс в язык стандарт ES6.
Уважаемые читатели! Встречались ли вы с ошибками, которые вызваны использованием оператора нестрогого равенства в JavaScript?