Как поставить обратные кавычки в js
Перейти к содержимому

Как поставить обратные кавычки в js

  • автор:

 

Руководство по JavaScript, часть 6: исключения, точка с запятой, шаблонные литералы

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

Обработка исключений

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

Рассмотрим следующий фрагмент кода.

Здесь у нас имеется функция, которую планируется использовать для обработки объектов, имеющих свойство value . Она возвращает это свойство. Если использовать эту функцию по назначению, то есть — передать ей такой объект, на работу с которым она рассчитана, при её выполнении ошибок выдано не будет. А вот если передать ей нечто неподходящее, в нашем случае — объявленную, но неинициализированную переменную, то при попытке обратиться к свойству value значения undefined произойдёт ошибка. В консоль попадёт сообщение об ошибке, выполнение программы остановится.

Вот как это выглядит при запуске данного кода в среде Node.js.

Исключение TypeError в Node.js

Если нечто подобное встретится в JS-коде веб-страницы, в консоль браузера попадёт похожее сообщение. Если такое произойдёт в реальной программе, скажем — в коде веб-сервера, подобное поведение крайне нежелательно. Хорошо было бы иметь механизм, который позволяет, не останавливая программу, перехватить ошибку, после чего принять меры по её исправлению. Такой механизм в JavaScript существует, он представлен конструкцией try. catch .

▍Конструкция try. catch

Конструкция try. catch позволяет перехватывать и обрабатывать исключения. А именно, в неё входит блок try , в который включают код, способный вызвать ошибку, и блок catch , в который передаётся управление при возникновении ошибки. В блоки try не включают абсолютно весь код программы. Туда помещают те его участки, которые могут вызвать ошибки времени выполнения. Например — вызовы функций, которым приходится работать с некими данными, полученными из внешних источников. Если структура таких данных отличается от той, которую ожидает функция, возможно возникновение ошибки. Вот как выглядит схема конструкции try. catch .

Если код выполняется без ошибок — блок catch (обработчик исключения) не выполняется. Если же возникает ошибка — туда передаётся объект ошибки и там выполняются некие действия по борьбе с этой ошибкой.

Применим эту конструкцию в нашем примере, защитив с её помощью опасные участки программы — те, в которых вызывается функция fn() .

Посмотрим на результаты выполнения этого кода в среде Node.js.

Обработка ошибки в Node.js

Как видите, если сравнить этот пример с предыдущим, теперь выполняется весь код, и тот, что расположен до проблемной строки, и тот, что расположен после неё. Мы «обрабатываем» ошибку, просто выводя в консоль значения свойства message объекта типа Error. В чём будет заключаться обработка ошибки, возникшей в реально используемом коде, зависит от ошибки.

Выше мы обсудили блок try. catch , но, на самом деле, эта конструкция включает в себя ещё один блок — finally .

▍Блок finally

Блок finally содержит код, который выполняется независимо от того, возникла или нет ошибка в коде, выполняющемся в блоке try . Вот как это выглядит.

Блок finally можно использовать и в том случае, если в блоке try. catch. finally отсутствует блок catch . При таком подходе он используется так же, как и в конструкции с блоком catch , например — для освобождения ресурсов, занятых в блоке try .

▍Вложенные блоки try

Блоки try могут быть вложены друг в друга. При этом исключение обрабатывается в ближайшем блоке catch .

В данном случае, если исключение возникнет во внутреннем блоке try , обработано оно будет во внешнем блоке catch .

▍Самостоятельное генерирование исключений

Исключения можно генерировать самостоятельно, пользуясь инструкцией throw . Вот как это выглядит.

После того, как выполняется эта инструкция, управление передаётся в ближайший блок catch , или, если такого блока найти не удаётся, выполнение программы прекращается. Значением исключения может быть всё что угодно. Например — определённый пользователем объект ошибки.

О точках с запятой

Использовать точки с запятой в JavaScript-коде необязательно. Некоторые программисты обходятся без них, полагаясь на автоматическую систему их расстановки, и ставя их только там, где это совершенно необходимо. Некоторые предпочитают ставить их везде, где это возможно. Автор этого материала относит себя к той категории программистов, которые стремятся обходиться без точек с запятой. Он говорит, что решил обходиться без них осенью 2017 года, настроив Prettier так, чтобы он удалял их везде, где без их явной вставки можно обойтись. По его мнению код без точек с запятой выглядит естественнее и его легче читать.

Пожалуй, можно сказать, что сообщество JS-разработчиков разделено, по отношению к точкам с запятой, на два лагеря. При этом существуют и руководства по стилю JavaScript, которые предписывают явную расстановки точек с запятой, и руководства, которые рекомендуют обходиться без них.

Всё это возможно из-за того, что в JavaScript существует система автоподстановки точек с запятой (Automatic Semicolon Insertion, ASI). Однако, то, что в JS коде, во многих ситуациях, можно обойтись без этих символов, и то, что точки с запятой расставляются автоматически, при подготовке кода к выполнению, не означает, что программисту не нужно знать правила, по которым это происходит. Незнание этих правил приводит к появлению ошибок.

▍Правила автоподстановки точек с запятой

Парсер JavaScript-кода автоматически добавляет точки с запятой при разборе текста программы в следующих ситуациях:

  1. Когда следующая строка начинается с кода, который прерывает текущий код (код некоей команды может располагаться на нескольких строках).
  2. Когда следующая строка начинается с символа > , который закрывает текущий блок.
  3. Когда обнаружен конец файла с кодом программы.
  4. В строке с командой return .
  5. В строке с командой break .
  6. В строке с командой throw .
  7. В строке с командой continue .

▍Примеры кода, который работает не так, как ожидается

Вот некоторые примеры, иллюстрирующие вышеприведённые правила. Например, как вы думаете, что будет выведено в результате выполнения следующего фрагмента кода?

При попытке выполнения этого кода будет выдана ошибка Uncaught TypeError: Cannot read property ‘forEach’ of undefined система, основываясь на правиле №1, пытается интерпретировать код следующим образом.

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

Вот ещё один фрагмент кода.

Результатом его выполнения станет вывод строки «3» . А что произойдёт, если нечто подобное появится в следующем фрагменте кода?

В данной ситуации появится ошибка TypeError: b is not a function так как вышеприведённый код будет интерпретирован следующим образом.

Взглянем теперь на пример, основанный на правиле №4.

Можно подумать, что это IIFE вернёт объект, содержащий свойство color , но на самом деле это не так. Вместо этого функция вернёт значение undefined так как система добавляет точку с запятой после команды return .

Для того чтобы решить подобную проблему, открывающую фигурную скобку объектного литерала нужно поместить в той же строке, где находится команда return .

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

Но он выводит 2, так как, в соответствии с правилом №1, этот код представляется следующим образом.

В вопросе использования точек с запятой в JavaScript стоит проявлять осторожность. Вы можете встретить как горячих сторонников точек с запятой, так и их противников. На самом деле, решая, нужны ли в вашем коде точки с запятой, можно положиться на тот факт, что JS поддерживает их автоматическую подстановку, но при этом каждый должен сам для себя решить — нужны ли они в его коде или нет. Главное — последовательно и разумно применять выбранный подход. В том, что касается расстановки точек с запятой и структуры кода, можно порекомендовать придерживаться следующих правил:

  • Пользуясь командой return , располагайте то, что она должна вернуть из функции, в той же строке, в которой находится эта команда. То же самое касается команд break , throw , continue .
  • Уделяйте особое внимание ситуациям, когда новая строка кода начинается со скобки, так как эта строка может быть автоматически объединена с предыдущей и представлена системой как попытка вызова функции или попытка доступа к элементу массива.

Кавычки и шаблонные литералы

Поговорим об особенностях использования кавычек в JavaScript. А именно, речь идёт о следующих допустимых в JS-программах типах кавычек:

  • Одинарные кавычки.
  • Двойные кавычки.
  • Обратные кавычки.

Разницы между ними практически нет. Пожалуй, единственное заметное различие заключается в том, что в строках, заключённых в одинарные кавычки, нужно экранировать символ одинарной кавычки, а в строках, заключённых в двойные — символ двойной.

В разных руководствах по стилю можно найти как рекомендацию по использованию одинарных кавычек, так и рекомендацию по использованию двойных кавычек. Автор этого материала говорит, что в JS-коде стремится использовать исключительно одинарные кавычки, используя двойные только в HTML-коде.

Обратные кавычки появились в JavaScript с выходом стандарта ES6 в 2015 году. Они, помимо других новых возможностей, позволяют удобно описывать многострочные строки. Такие строки можно задавать и используя обычные кавычки — с применением escape-последовательности \n . Выглядит это так.

Обратные кавычки (обычно кнопка для их ввода находится левее цифровой клавиши 1 на клавиатуре) позволяют обойтись без \n .

Но этим возможности обратных кавычек не ограничены. Так, если строка описана с использованием обратных кавычек, в неё, используя конструкцию $<> , можно подставлять значения, являющиеся результатом вычисления JS-выражений.

Такие строки называют шаблонными литералами.

Шаблонные литералы отличаются следующими особенностями:

  • Они поддерживают многострочный текст.
  • Они дают возможность интерполировать строки, в них можно использовать встроенные выражения.
  • Они позволяют работать с тегированными шаблонами, давая возможность создавать собственные предметно-ориентированные языки (DSL, Domain-Specific Language).

▍Многострочный текст

Задавая, с помощью обратных кавычек, многострочные тексты, нужно помнить о том, что пробелы в таких текстах так же важны, как и другие символы. Например, рассмотрим следующий многострочный текст.

Его вывод даст примерно следующее.

То есть оказывается, что когда этот текст вводился в редакторе, то, возможно, программист ожидал, что слова First и Second , при выводе, окажутся строго друг под другом, но на самом деле это не так. Для того чтобы обойти эту проблему, можно начинать многострочный текст с перевода строки, и, сразу после закрывающей обратной кавычки, вызывать метод trim() , который удалит пробельные символы, находящиеся в начале или в конце строки. К таким символам, в частности, относятся пробелы и знаки табуляции. Удалены будут и символы конца строки.

Выглядит это так.

▍Интерполяция

Под интерполяцией здесь понимается преобразование переменных и выражений в строки. Делается это с использованием конструкции $<> .

В блок $<> можно добавлять всё что угодно — даже выражения.

В константу string попадёт текст something 6 , в константу string2 будет записан либо текст something x , либо текст something y . Это зависит от того, истинное или ложное значение вернёт функция foo() (здесь применяется тернарный оператор, который, если то, что находится до знака вопроса, является истинным, возвращает то, что идёт после знака вопроса, в противном случае возвращая то, что идёт после двоеточия).

▍Тегированные шаблоны

Тегированные шаблоны применяются во множестве популярных библиотек. Среди них — Styled Components, Apollo, GraphQL.

То, что выводят такие шаблоны, подчиняется некоей логике, задаваемой с помощью функции. Вот немного переработанный пример, приведённый в одной из наших публикаций, иллюстрирующий работу с тегированными шаблонными строками.

Здесь, если в константе esth записано число 8 , в es попадёт строка ES 8 is awesome . В противном случае там окажется другая строка. Например, если в esth будет число 6 , то она будет выглядеть как ES 6 is good .

В Styled Components тегированные шаблоны используются для определения CSS-строк.

В Apollo они применяются для определения GraphQL-запросов.

Зная то, как устроены тегированные шаблоны, несложно понять, что styled.button и gql из предыдущих примеров — это просто функции.

Например, функция gql() возвращает строку, которая может быть результатом любых вычислений. Параметр literals этой функции представляет собой массив, содержащий разбитое на части содержимое шаблонного литерала, expresions содержит результаты вычисления выражений.

Разберём следующую строку.

В функцию helper попадёт массив literals , содержащий два элемента. В первом будет текст something с пробелом после него, во втором — пустая строка — то есть то, что находится между выражением $ <1 + 2 + 3>и концом строки. В массиве espressions будет один элемент — 6 .
Вот более сложный пример.

Здесь в функцию helper , в качестве первого параметра попадёт следующий массив.

Второй массив будет выглядеть так.

Итоги

Сегодня мы поговорили об обработке исключений, об автоподстановке точки с запятой и о шаблонных литералах в JavaScript. В следующий раз мы рассмотрим ещё некоторые важные концепции языка. В частности — работу в строгом режиме, таймеры, математические вычисления.

Уважаемые читатели! Пользуетесь ли вы возможностями тегированных шаблонов в JavaScript?

Строки в JavaScript

В JavaScript любые текстовые данные являются строками. Внутренний формат для строк — всегда UTF-16, вне зависимости от кодировки страницы.

Строки в JS обозначаются кавычками:
  1. одинарными ( ‘Привет’ );
  2. двойными ( «Привет» );
  3. обратными(для шаблонных литералов):
  • позволяют вставлять в строку произвольные (вычисляемые) выражения или переменные, обернув их в $ <…>);
  • могут занимать более одной строки (без использования спецсимволов).

Шаблонные литералы (строки) в JavaScript

Шаблонными литералами называются строковые литералы, допускающие использование выражений внутри, обозначаемых знаком $ и фигурными скобками ( $ <выражение>). Заключаются в обратные кавычки ( ) (буква «ё»). Позволяют использовать многострочные литералы и строковую интерполяцию.

Шаблон строки в JavaScript

Спецсимволы в строках JS

Многострочные строки также можно создавать с помощью одинарных и двойных кавычек, используя так называемый «символ перевода строки», который записывается как \n :

JavaScript строки (string)

Тип данных строка (string) используется для представления текста. Соответственно, значениями типа string является текст. Любой текст в JavaScript является строкой.

Кавычки

Строки в JavaScript должны быть заключены в кавычки. В JavaScript существует три вида кавычек: двойные ( » » ), одинарные ( ‘ ‘ ) и обратные ( ` ` ):

Вид кавычек в начале и конце строки должен совпадать.

Строки могут состоять из нуля и более символов:

Строки с двойными и одинарными кавычками ничем не отличаются между собой по функционалу – они могут содержать лишь текст и управляющие последовательности. А вот строки с обратными кавычками имеют более широкий функционал. Такие строки могут содержать так называемые подстановки, обозначаемые знаком доллара и фигурными скобками $ <выражение>. Подстановки могут содержать любые произвольные выражения:

Выражение, расположенное в подстановке ( $ <. >) вычисляется, и его результат становится частью строки.

 

Строки в обратных кавычках могут занимать более одной строки, сохраняя все пробельные символы:

Строки с обратными кавычками называются строками-шаблонами или шаблонными литералами.

Строки, заключённые в одни кавычки, могут содержать другие кавычки:

Для удобства, большие строковые литералы можно разбивать на несколько строк, заканчивая каждую строку, кроме последней, символом \ :

Кодировка символов строки

Вне зависимости от того, какая кодировка установлена для страницы, в JavaScript для строк всегда используется кодировка UTF-16.

В JavaScript строка – это неизменяемая, упорядоченная последовательность 16-битных значений, каждое из которых представляет символ Unicode. Для представления символов Unicode в JavaScript используется кодировка UTF-16. Символы включают в себя буквы, цифры, знаки пунктуации, специальные символы и пробельные символы.

Длина строки

Длина строки – это количество 16-битных значений (а не самих символов), содержащихся в ней. Длину строки содержит свойство length :

Символы, кодовые пункты которых не умещаются в 16 бит, обрабатываются в соответствии с правилами кодировки UTF-16 как последовательности из двух 16-битных значений. Это означает, что строка, имеющая длину, равную 2 (два 16-битных значения), на деле может представлять единственный символ:

Нумерация и доступ к символам строки

Как уже было сказано, строка представляет собой упорядоченную последовательность 16-битных значений, каждому из которых соответствует определённый символ. Нумерация 16-битных значений в строке начинается с нуля, т. е. первое 16-битное значение находится под индексом 0, второе – под индексом 1 и т. д. Индекс – это порядковый номер.

Получить символ строки (состоящий из одного 16-битного значения) можно с помощью индекса, заключённого в квадратные скобки [индекс] :

Чтобы с помощью индексов обратиться к символу, состоящему из двух 16-битных значений, нужно, используя конкатенацию, написать эти индексы так, чтобы в результате получилась последовательность из двух 16-битных значений:

Строки неизменяемые

В JavaScript строки неизменяемые. Это значит, что в уже существующей строке нельзя менять никакие символы или добавлять в неё что-то новое.

Так как строки неизменяемые, то методы, используемые для работы со строками, возвращают новые строки, а не изменяют ту строку, относительно которой они были вызваны:

Чтобы изменить строку, можно создать новую строку и записать её в ту же самую переменную вместо старой строки:

Управляющие последовательности

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

В таблице ниже представлены управляющие последовательности:

Последовательность Значение
\0 Символ NUL – пустой символ ( «\u0000» ).
\t Горизонтальная табуляция ( «\u0009» ).
\n Перевод на новую строку ( «\u000A» ).
\b Возврат на одну позицию – то, что происходит при нажатии на клавишу backspace ( «\u0008» ).
\r Возврат каретки ( «\u000D» ).
\f Перевод страницы – очистка страницы ( «\u000C» ).
\v Вертикальная табуляция ( «\u000B» ).
Двойная кавычка ( «\u0022» ).
\’ Одинарная кавычка ( «\u0027» ).
\\ Обратный слэш ( «\u005C» ).
\xNN Номер символа из набора символов ISO Latin-1, заданный двумя шестнадцатеричными цифрами ( N – шестнадцатеричная цифра 0-F ). Например, «\x41» (это код буквы «A» ).
\uNNNN Номер символа из набора символов Unicode, заданный четырьмя шестнадцатеричными цифрами ( N – шестнадцатеричная цифра 0-F ). Например, «\u0041» (это код буквы «A»s ).

Управляющие последовательности могут находиться в любом месте строки:

Если символ \ предшествует любому символу, отличному от приведённых в таблице, то он просто игнорируется интерпретатором:

Символы Unicode, указываемые с помощью управляющей последовательности, можно использовать не только внутри строковых литералов, но и в идентификаторах:

Конкатенация

Конкатенация — это объединение двух или более строк в одну большую. Объединение происходит с помощью оператора + (плюс). При конкатенации каждая последующая строка добавляется в конец предыдущей:

Значение любого типа, которое объединяется со строкой, будет неявно (автоматически) преобразовано в строку и далее будет произведена конкатенация.

ES6 в деталях: шаблонные строки

На прошлой неделе я обещал сбавить темп. Я говорил, что после итераторов и генераторов мы возьмёмся за что-нибудь полегче, что-то, что не вынесет вам мозг. Посмотрим, смогу ли сдержать своё обещание.

А пока начнём с чего-нибудь простого.

Обратные кавычки

В ES6 появился новый вид синтаксиса строкового литерала под названием шаблонные строки. Они выглядят как обычные строки за исключением того, что обёрнуты символами обратных кавычек ` вместо обычных кавычек ‘ или » . И в простейшем случае это действительно всего лишь строки.

Но они неспроста называются «шаблонные строки», а не «старые и скучные ничем не примечательные обыкновенные строки, но только с обратными кавычками». Вместе с шаблонными строками в JavaScript появляется простая строковая интерполяция. Иными словами, это способ опрятно и удобно подставлять значения JavaScript в строки.

Их можно применять в миллионах случаев, но моё сердце греет такое скромное сообщение об ошибке:

В этом примере $ and $ называются шаблонными подстановками. JavaScript вставит значения user.name и action в получившуюся строку. Так можно сгенерировать сообщение вроде Пользователю jorendorff не разрешено играть в хоккей. (Что между прочим, правда. У меня нет хоккейной лицензии.)

Пока что это просто слегка более опрятный синтаксис оператора + , но есть несколько деталей, на которые следует обратить внимание:

Код в шаблонной подстановке может быть любым выражением JavaScript, так что вызовы функций, арифметика и т.п. разрешены. (Если вы действительно хотите, то можете поместить в шаблонной строке другую шаблонную строку, я это называю шаблонным Началом.)

Если какое-то значение не строкового типа, оно будет приведено к строке при помощи обычных правил. К примеру, если action — объект, у него вызовется метод .toString() .

Если вам нужно использовать символ обратной кавычки в шаблонной строке, её нужно экранировать обратным слэшем: `\« — это то же самое, что «`» .

В отличие от обычных строк, в шаблонных строках можно использовать символы переноса строк:

Все пробельные символы в шаблонной строке, включая переносы строк и отступы, включаются «как есть» в результат.

Хорошо. Из-за того, что я пообещал на прошлой неделе, я чувствую свою ответственность за сохранность вашего мозга. Можете прекратить читать прямо сейчас, возможно, пойти выпить чашечку кофе и насладиться своим невредимым мозгом, который все еще находится в вашей черепной коробке. Серьёзно, нет ничего постыдного в том, чтобы отступить. Разве Лопес Гонсальвес ринулся целиком исследовать южное полушарие после того, как доказал, что суда могут пересекать экватор не будучи разбитыми морскими чудищами и не падая с края Земли? Нет. Он повернул обратно домой и хорошенько пообедал. Вам же нравится обедать, верно?

С обратными кавычками в будущее

Давайте поговорим немного о том, чего шаблонные строки не делают.

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

Неочевидно, как они должны работать с библиотекой интернационализации (эта библиотека позволяет вашему коду разговаривать на разных языках с разными пользователями). Шаблонные строки не поддерживают форматирование чисел и дат в зависимости от языка, и даже не помогут с плюрализацией.

Они не замена библиотекам-шаблонизаторам вроде Mustache или Nunjucks.

Шаблонные строки не обладают каким-либо встроенным синтаксисом для циклов, например для генерации строк таблицы из массива. В них нет даже условных операторов. (Да, вы можете воспользоваться шаблонным Началом для этих целей, но мне кажется, что такое стоит делать разве что ради прикола.)

У шаблонных строк в ES6 есть ещё один козырь, который позволяет программистам и разработчикам библиотек не только обойти эти ограничения, но ещё и много чего другого. То, о чём я говорю, называется помеченными шаблонами.

Синтаксис помеченных шаблонов прост. Это просто шаблонные строки с добавленной меткой перед открывающей обратной кавычкой. В нашем первом примере меткой будет SaferHTML , и мы воспользуемся этой меткой чтобы обойти первое ограничение из списка, автоматическое экранирование спецсимволов.

Обратите внимание, SaferHTML — это не что-то, что предоставляется стандартной библиотекой. Сейчас мы напишем её сами.

В качестве метки здесь выступает одиночный идентификатор SaferHTML , но меткой также может быть свойство, например SaferHTML.escape , или даже вызов метода, например SaferHTML.escape() . (Если быть совсем точным, любое выражение MemberExpression или CallExpression может быть тегом.)

Мы видели, что шаблонные строки без меток — это краткий способ простой строковой конкатенации. Помеченные шаблоны — это нечто совсем другое, вызов функции.

Код выше эквивалентен такому:

где templateData — это неизменяемый массив всех частей строки в шаблоне, созданный движком JS. В нашем случае в массиве будет два элемента, потому что в помеченной шаблонной строке две части, разделённых подстановкой. Так что templateData будет Object.freeze ([«<p>», » отвесил вам леща.</p>»])

(На самом деле, в templateData есть ещё одно свойство, templateData.raw — это другой массив, содержащий все строковые части шаблона, но на этот раз они в точности в таком виде, в каком они были в исходном коде. Экранирующие последовательности вроде \n оставлены в них как есть, вместо того, чтобы превратиться в перевод каретки, ну и тому подобное. Стандартная метка String.raw использует эти сырые строки.)

Это даёт функции SaferHTML свободу интерпретировать как строку, так и подстановки миллионом различных способов.

Прежде чем продолжить чтение, может быть вы захотите попробовать разобраться в том, что SaferHTML должна делать и попробуете вручную её реализовать? В конце концов, это же всего лишь обычная функция. Мы можете проверять, что у вас получается, в консоли разработчика в Firefox.

Вот одно из возможных решений (также доступное как gist).

В таком определении помеченный шаблон SaferHTML`<p>$ отвесил вам леща.</p>` может развернуться в строку «<p>ES6&lt;3er отвесил вам леща.</p>» . Ваши пользователи в безопасности даже если пользователь со зловредным именем вроде Хакер Стив <script>alert(‘xss’);</script> отвесит им леща. Что бы это ни значило.

(Кстати, если такой способ использования функцией объекта arguments кажется вам неуклюжим, заходите на следующей неделе. В ES6 есть ещё одна фича, которая, думаю, вам понравится.)

Одного примера будет недостаточно, чтобы продемонстрировать всю гибкость помеченных шаблонов. Давайте вернёмся как нашему списку выше, с ограничениями шаблонных строк, чтобы посмотреть, что ещё можно делать.

Шаблонные строки не экранируют спецсимволы автоматически. Но, как мы увидели, с помеченными шаблонами вы можете исправить это дело самостоятельно, написав метку.

Вообще говоря, можно делать даже намного лучше.

С точки зрения безопасности моя функция SaferHTML достаточно слабая. В разных местах HTML есть разные спецсимволы, которые нужно по-разному экранировать, и SaferHTML экранирует не все из них. Но приложив небольшое усилие вы могли бы написать намного более умную функцию SaferHTML , которая разбирает куски HTML в строках из массива templateData , чтобы узнать, какие подстановки в простом HTML; какие из них внутри атрибутов и требуют ещё и экранирования ‘ и » ; какие в строке запроса в URL и должны экранироваться как в URL, а не как в HTML; ну и так далее. Она могла бы применять нужное экранирование к каждой подстановке.

Вам кажется, что это оторвано от реальности, потому что разбор HTML медленный? К счастью, строковые части помеченного шаблона не меняются, когда шаблон вычисляется повторно. SaferHTML могла бы кэшировать результаты этого разбора для ускорения будущих вызовов. (Этим кэшем может быть WeakMap, другая функциональность ES6, которую мы обсудим в будущих статьях.)

У шаблонных строк нет встроенных средств для интернационализации. Но с метками мы можем их добавить.

Статья Джека Хсу (Jack Hsu) демонстрирует первые шаги к тому, как это будет выглядеть. Один пример для привлечения внимания:

Заметьте, что в этом примере name и amount — JavaScript, но есть ещё и немного незнакомого кода, вот это :c(CAD) , которое Джек помещает в строковую часть шаблона. JavaScript, само собой, обрабатывается движком JavaScript, строковые же части обрабатываются написанной Джеком меткой i18n . Из документации пользователь может узнать, что :c(CAD) обозначает, что amount — это количество валюты, переведённое в канадские доллары.

Вот, для чего и нужны помеченные шаблоны.

Шаблонные строки не заменяют Mustache и Nunjucks, отчасти из-за того, что в них не встроен синтаксис для циклов и условий. Но теперь-то мы начинаем видеть, как это можно исправить, верно? Если в JS нет какой-то функциональности, можно написать метку, которая её реализует.

Гибкость этим не ограничивается. Заметьте, что аргументы функции-метки не приводятся автоматически к строкам. Они могут быть чем угодно. То же самое касается и возвращаемого значения. Помеченные шаблоны даже не обязательно должны быть строками! Вы можете использовать собственные метки, чтобы создавать регулярки, деревья DOM, изображения, промисы над целыми асинхронными процессами, структуры данных JS, шейдеры GL…

Помеченные шаблоны призывают разработчиков библиотек создавать мощные предметно-ориентированные языки. Эти языки могут быть вообще непохожими на JS, но при этом встраиваться в JS как влитые и разумно взаимодействовать с остальным языком. Я сходу не могу вспомнить ничего подобного в других языках. Я не знаю, к чему эта возможность нас приведёт. Возможности потрясающие.

Когда можно начинать этим пользоваться?

На сервере шаблонные строки поддерживаются в io.js уже сегодня.

Из браузеров их поддерживает Firefox 34+. В Chrome поддержка зависит от настройки «Экспериментальный JavaScript», которая по умолчанию выключена. Пока что, если вы хотите применять шаблонные строки в вебе, нужно пользоваться Babel или Traceur. Вы также можете использовать их прямо сейчас в TypeScript!

Подождите! А что насчёт Markdown?

Ой. …Хороший вопрос.

(Этот раздел не про JavaScript. Если вы не пользуетесь Markdown, можете смело его пропускать.)

С появлением шаблонных строк выходит, что и Markdown и JavaScript теперь используют один и тот же символ ` для обозначения чего-то особенного. Фактически, в Markdown это разделитель кусков кода посреди обычного текста.

А вот тут небольшая проблема! Если вы напишете в документе Markdown так:

то оно отобразится как:

Чтобы показать сообщение, напишите alert( hello world! ) .

Заметьте, на выходе нет обратных кавычек. Markdown интерпретировал все четыре обратные кавычки как разделители кода и заменил их на теги HTML.

Чтобы обойти эту напасть, мы обратимся к одной малоизвестной возможности, которая была в Markdown с самого начала: вы можете использовать несколько обратных кавычек как разделители кода, вот так:

В этом Gist все подробности на эту тему, и он написан на Markdown, так что вы можете посмотреть на исходник.

Что дальше

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

Мы посмотрим на них глазами человека, который реализовал их в Firefox. Так что пожалуйста присоединяйтесь к нам на следующей неделе, и наш приглашённый автор Бенджамин Петерсон (Benjamin Peterson) представит в деталях параметры по умолчанию и остаточные параметры из ES6.

 

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *