Одинарные, двойные и обратные кавычки в JavaScript
Перевод статьи «The real difference between ‘single quotes’ and “double quotes” in JavaScript».
Photo by Vlada Karpovich from Pexels
Какие кавычки стоит использовать в JavaScript: одинарные или двойные? Ответ меня удивил: эти варианты совершенно идентичны, если не рассматривать вопрос экранирования.
«В JavaScript одинарные и двойные кавычки ведут себя совершенно одинаково», — пишет Мэтью Холман в своей статье на cloudboost.io.
И одинарные, и двойные кавычки в коде на JS используются довольно часто. С их помощью создаются строковые литералы.
«Литерал» — это просто еще одно слово, которым обозначается значение переменной (в то время как имя переменной — это ссылка).
Единственная разница между одинарными и двойными кавычками в JS связана с экранированием кавычек внутри строковых литералов.
Одинарные кавычки
Если строковый литерал образован при помощи одинарных кавычек ( » ), другие одинарные кавычки внутри него нужно экранировать при помощи обратного слэша ( \’ ).
Двойные кавычки
Аналогично, если строковый литерал образован при помощи двойных кавычек ( «» ), другие двойные кавычки внутри него тоже нужно экранировать при помощи обратного слэша ( \’ ).
Примечание редакции Techrocks. Экранирование не требуется, если для создания литерала вы использовали один тип кавычек, а внутри него — другой.
«Empty» === ‘Empty’
Пара двойных или одинарных кавычек может представлять пустую строку, не содержащую никаких символов.
Не лучше ли использовать обратные кавычки?
В ES6 появились шаблонные литералы, которые создаются при помощи обратных кавычек ( « ).
«Шаблонными литералами называются строковые литералы, допускающие использование выражений внутри. С ними вы можете использовать многострочные литералы и строковую интерполяцию», — MDN.
Эти литералы имеют три больших преимущества:
1. Более простая конкатенация («интерполяция переменных»)
2. Отпадает необходимость экранировать одинарные или двойные кавычки
3. Многострочный код можно писать без символов новой строки (\n)
Обратные кавычки также больше подходят для HTML:
Шаблонные литералы не уступают по скорости строковым. Так почему бы не использовать повсеместно обратные кавычки?
Не забывайте о JSON
Легковесный формат хранения данных JSON допускает использование только двойных кавычек.
Если мне нужно постоянно копировать код из JavaScript в файлы JSON и обратно, использование двойных кавычек поможет поддерживать единообразие. Это случается довольно редко, так что мне приходится напоминать себе не использовать одинарные кавычки в JSON.
Функции stringify() и parse() , которые используются для работы с файлами JSON внутри JavaScript, знают о двойных кавычках:
Как видно из примера, одинарные кавычки мешают распарсить JSON.
С технической точки зрения причина этого — в спецификации JSON (RFC 7159), где есть требование использования именно двойных кавычек.
Почему бы не использовать все три вида кавычек?
Да, нет ничего дурного в том, чтобы использовать двойные кавычки по умолчанию, одинарные — внутри строк, если там они нужны по смыслу, а обратные — для включения переменных или написания многострочных литералов.
Все сводится к личным предпочтениям, хотя многие люди выступают за то, чтобы остановиться на каком-то одном варианте и использовать исключительно его.
Например, руководство по стилю Airbnb предписывает отдавать предпочтение одинарным кавычкам, избегать использования двойных, а обратные использовать пореже.
Для обеспечения единообразия используйте ESLint
Если последовательность стиля имеет для вас значение (как и для разработчиков Airbnb), ее легко обеспечить при помощи ESLint:
- Правило quotes в ESLint может требовать использования двойных кавычек (по умолчанию), а одинарных или обратных — там, где это возможно.
- Это правило также может требовать применения только одного вида кавычек. (За исключением случаев, если строка содержит символ кавычки, который придется экранировать).
- Наконец, ESLint может требовать использования одинарных или двойных кавычек и при этом допускать использование обратных для создания шаблонных литералов.
Используйте Prettier и вообще забудьте об этой проблеме
Более простое решение, чем использовать ESLint для обеспечения единообразия стиля, — использовать Prettier для автоматического форматирования.
В Prettier по умолчанию используются двойные кавычки. Но его можно легко переключить на использование одинарных (по крайней мере, в CodeSandbox.io).
Для Prettier также есть соответствующее расширение в VSCode.
Мои личные предпочтения
В своем коде я склонен использовать двойные и обратные кавычки, хотя подумываю об использовании исключительно обратных.
Prettier я использую с дефолтными установками для двойных кавычек — просто привык к этому.
Хотя я осознаю пользу единообразия в коде, я не думаю, что кавычки играют в этом очень уж большую роль.
Но если придется выбирать, думаю, стоит остановиться на обратных кавычках, поскольку шаблонные литералы имеют преимущества вроде интерполяции и многострочности.
Способы построения строк в ES6 — Шаблонные литералы
Строки это очень важная часть программирования. Здесь мы вспомним, как было принято работать со строками ранее – до появления спецификации ES6 .
И потом узнаем о более простом способе построения строк с помощью, так называемых, шаблонных литералов, используя которые можно удобнее и быстрее создавать комплексные и многострочные строки. И тем самым писать более правильный и чистый код .
Начнем с создания новых переменных, которые потом мы сможем объединить в одну большую строку.
Теперь, нужно использовать эти переменные для построения следующей строки:
Построение комплексной строки
Вот как выглядит построение строки из других строк и переменных в JavaScript. Это стандартный способ, существующий до появления спецификации ES6 :
Пример 1.1
На что здесь нужно обратить внимание?
1. Здесь для слова "I’m" обязательно используются двойные кавычки, так как оно уже содержит в себе апостроф (одинарную кавычку). Это правило относится ко всем словам, содержащим апостроф, например "it’s" , "does’t" и др.
2. Выражение (year — birthYear) выполняется в первую очередь, поэтому оно заключено в скобки. Сначала нужно узнать, сколько индивиду лет. Из таблицы приоритета операторов нам известно, что группировка, то есть скобки (. ) имеют самый высокий приоритет. И только после этого работает сложение, то есть будут складываться элементы выражения в одну строку.
3. Интересен еще один момент: результатом выражения (year — birthYear) будет число, в то время как остальные элементы общего выражения — это строки. Если у кого-то возникает вопрос: как это будет работать? То опять же это пройденный материал — статья «Преобразование или приведение типов в JavaScript» — раздел преобразование чисел. То есть в данном случае JavaScript просто преобразовывает число в строку, после чего объединяет уже только строки.
4. При составлении подобных выражений нужно быть внимательным и следить за пробелами при сложении строк. Например, эта часть выражения: ‘, a ‘ — здесь нужен пробел перед артиклем a и после него. Это бывает не просто, особенно, когда выражения громоздки.
Итак, при составлении подобных сложных/комплексных строк, возникают определенные сложности : нужно расставлять пробелы и знаки сложения. Это не всегда удобно.
Теперь, начиная со стандарта ES6, существует хороший инструмент для выполнения такого рода вещей, который называется шаблонные литералы.
Шаблонные литералы
С шаблонными литералами появилась возможность составления комплексных строк более нормальным/удобным способом . При этом переменные вставляются непосредственно в строку.
Давайте посмотрим, как это работает.
Создаем новую переменную и пишем шаблонный литерал .
Пример 2.1
В примере используется определённый вид кавычек . Это обратный апостроф или гравис . Этот символ расположен на клавише Ё . Его также называют обратное ударение или обратные одинарные кавычки.
Итак, гравис используется для того, чтобы дать понять Javascript, что мы пишем шаблонную строку . При этом двойные или одиночные кавычки здесь работать не будут .
Итак, что происходит внутри обратных кавычек? Мы просто пишем строку и там, где нужно вставляем переменные. Для вставки переменных используется знак доллара, фигурные скобки и указывается имя переменной.
Далее, чтобы посмотреть, действительно ли это работает, выводим новую переменную в консоль.
Пример показывает, что в случае с шаблонными литералами все делается намного проще .
И чтобы окончательно в этом убедиться построим комплексную строку заново, используя шаблонные литералы.
Пример 2.2
Как видно из примера, использование шаблонных литералов в JavaScript упрощает построение строки , так как при этом уже не нужно использовать сложение "+", не нужно думать о том, что где-то мы можем пропустить пробел, как это нередко бывает. Это намного проще.
Итак, теперь вы знаете, как работают шаблонные литералы, определенные в спецификации ES6 JavaScript . И в действительности, это одна из наиболее часто используемых особенностей привнесенных вместе с ES6 .
Обратный апостроф — Для всех строк
Следует знать, что обратный апостроф или гравис можно использовать для написания всех строк .
В примере выше мы работали с неоднородной/комплексной строкой: где кроме простого текста используется вставка переменных. Следующим образом: $
Так вот обратный апостроф или гравис может использоваться и для простых строк.
Пример 3.1
Многие разработчики уже начали использовать обратный апостроф для всех строк . Потому что при этом не нужно задумываться над тем, какой вид кавычек использовать. Проще использовать обратные кавычки (гравис) всегда . В этом есть смысл.
Многострочные строки
Рассмотрим еще один пример использования шаблонных литералов — это создание многострочных строк . Здесь шаблонные литералы также имеют преимущество, так как раньше многострочные строки были немного громоздки, не удобны для написания и для восприятия.
Вот как это выглядело до внедрения стандарта ES6:
Пример 4.1
Из примера видно, что каждый раз для переноса строки дважды используется обратный слеш и буква n между ними \n\ . Так работал JavaScript в прошлом и считается, что подобные методы — это недоработки в языке .
С появлением версии ES6 и шаблонных литералов нет необходимости в использовании дополнительных символов . Сейчас, используя обратные кавычки, для переноса стоки достаточно нажать Enter .
Пример 4.2
Такой способ построения строк будет очень полезен позже, когда начнется совместное использовани е HTML и JavaScript . При этом будут создаваться многострочные HTML-элементы, которые будут использоваться для вставки на динамические страницы. Это будет интересно.
Итак, теперь для создания комплексных или многострочных строк , всегда используйте шаблонные литералы, потому что этот способ и такой код является более чистым и правильным.
ES6 в деталях: шаблонные строки
На прошлой неделе я обещал сбавить темп. Я говорил, что после итераторов и генераторов мы возьмёмся за что-нибудь полегче, что-то, что не вынесет вам мозг. Посмотрим, смогу ли сдержать своё обещание.
А пока начнём с чего-нибудь простого.
Обратные кавычки
В ES6 появился новый вид синтаксиса строкового литерала под названием шаблонные строки. Они выглядят как обычные строки за исключением того, что обёрнуты символами обратных кавычек ` вместо обычных кавычек ‘ или » . И в простейшем случае это действительно всего лишь строки.
Но они неспроста называются «шаблонные строки», а не «старые и скучные ничем не примечательные обыкновенные строки, но только с обратными кавычками». Вместе с шаблонными строками в JavaScript появляется простая строковая интерполяция. Иными словами, это способ опрятно и удобно подставлять значения JavaScript в строки.
Их можно применять в миллионах случаев, но моё сердце греет такое скромное сообщение об ошибке:
В этом примере $
Пока что это просто слегка более опрятный синтаксис оператора + , но есть несколько деталей, на которые следует обратить внимание:
Код в шаблонной подстановке может быть любым выражением JavaScript, так что вызовы функций, арифметика и т.п. разрешены. (Если вы действительно хотите, то можете поместить в шаблонной строке другую шаблонную строку, я это называю шаблонным Началом.)
Если какое-то значение не строкового типа, оно будет приведено к строке при помощи обычных правил. К примеру, если action — объект, у него вызовется метод .toString() .
Если вам нужно использовать символ обратной кавычки в шаблонной строке, её нужно экранировать обратным слэшем: `\« — это то же самое, что «`» .
В отличие от обычных строк, в шаблонных строках можно использовать символы переноса строк:
Все пробельные символы в шаблонной строке, включая переносы строк и отступы, включаются «как есть» в результат.
Хорошо. Из-за того, что я пообещал на прошлой неделе, я чувствую свою ответственность за сохранность вашего мозга. Можете прекратить читать прямо сейчас, возможно, пойти выпить чашечку кофе и насладиться своим невредимым мозгом, который все еще находится в вашей черепной коробке. Серьёзно, нет ничего постыдного в том, чтобы отступить. Разве Лопес Гонсальвес ринулся целиком исследовать южное полушарие после того, как доказал, что суда могут пересекать экватор не будучи разбитыми морскими чудищами и не падая с края Земли? Нет. Он повернул обратно домой и хорошенько пообедал. Вам же нравится обедать, верно?
С обратными кавычками в будущее
Давайте поговорим немного о том, чего шаблонные строки не делают.
Они не экранируют автоматически спецсимволы. Чтобы избегать уязвимостей межсайтового скриптинга, вам всё ещё нужно обращаться с ненадёжными данными с осторожностью, точно так же, как при конкатенации обычных строк.
Неочевидно, как они должны работать с библиотекой интернационализации (эта библиотека позволяет вашему коду разговаривать на разных языках с разными пользователями). Шаблонные строки не поддерживают форматирование чисел и дат в зависимости от языка, и даже не помогут с плюрализацией.
Они не замена библиотекам-шаблонизаторам вроде Mustache или Nunjucks.
Шаблонные строки не обладают каким-либо встроенным синтаксисом для циклов, например для генерации строк таблицы из массива. В них нет даже условных операторов. (Да, вы можете воспользоваться шаблонным Началом для этих целей, но мне кажется, что такое стоит делать разве что ради прикола.)
У шаблонных строк в ES6 есть ещё один козырь, который позволяет программистам и разработчикам библиотек не только обойти эти ограничения, но ещё и много чего другого. То, о чём я говорю, называется помеченными шаблонами.
Синтаксис помеченных шаблонов прост. Это просто шаблонные строки с добавленной меткой перед открывающей обратной кавычкой. В нашем первом примере меткой будет SaferHTML , и мы воспользуемся этой меткой чтобы обойти первое ограничение из списка, автоматическое экранирование спецсимволов.
Обратите внимание, SaferHTML — это не что-то, что предоставляется стандартной библиотекой. Сейчас мы напишем её сами.
В качестве метки здесь выступает одиночный идентификатор SaferHTML , но меткой также может быть свойство, например SaferHTML.escape , или даже вызов метода, например SaferHTML.escape(
Мы видели, что шаблонные строки без меток — это краткий способ простой строковой конкатенации. Помеченные шаблоны — это нечто совсем другое, вызов функции.
Код выше эквивалентен такому:
где templateData — это неизменяемый массив всех частей строки в шаблоне, созданный движком JS. В нашем случае в массиве будет два элемента, потому что в помеченной шаблонной строке две части, разделённых подстановкой. Так что templateData будет Object.freeze ([«<p>», » отвесил вам леща.</p>»])
(На самом деле, в templateData есть ещё одно свойство, templateData.raw — это другой массив, содержащий все строковые части шаблона, но на этот раз они в точности в таком виде, в каком они были в исходном коде. Экранирующие последовательности вроде \n оставлены в них как есть, вместо того, чтобы превратиться в перевод каретки, ну и тому подобное. Стандартная метка String.raw использует эти сырые строки.)
Это даёт функции SaferHTML свободу интерпретировать как строку, так и подстановки миллионом различных способов.
Прежде чем продолжить чтение, может быть вы захотите попробовать разобраться в том, что SaferHTML должна делать и попробуете вручную её реализовать? В конце концов, это же всего лишь обычная функция. Мы можете проверять, что у вас получается, в консоли разработчика в Firefox.
Вот одно из возможных решений (также доступное как gist).
В таком определении помеченный шаблон SaferHTML`<p>$
(Кстати, если такой способ использования функцией объекта 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.
Обратные одинарные кавычки — что это за символы
Обратные одинарные кавычки — это одинарные кавычки с «наклонов вправо», в то время как обычные одинарные кавычки «смотрят прямо вниз».
Пара обычных одинарных:
Пара одинарных обратных:
Обратная одинарная кавычка на клавиатуре
Находятся на клавиатуре компьютера там же, где буква Ё (в русской раскладке) — слева вверху под клавишей «Esc».