Строки

Строку можно записать в одинарных кавычках 'привет' или в двойных "привет" – для языка это одно и то же, выберите один стиль и придерживайтесь его (в этом курсе – одинарные).

Три вида кавычек

quotes.jsjs
const a = 'привет';  // одинарные// двойные – для языка то же самоеconst b = "привет";
Два равнозначных вида: разница только в стиле.

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

Отсюда правило: если внутри текста нужна кавычка, снаружи берут другой вид"д'Артаньян", 'Он сказал: "привет"'. Когда оба вида нужны разом, кавычку экранируют – ставят перед ней обратную косую черту. Черта снимает с кавычки служебную роль, и та становится обычным символом текста.

quotes-broken.jsjs
const bad = 'д'Артаньян';
Консоль
SyntaxError: Unexpected identifier 'Артаньян'
Строка кончилась на второй кавычке. Ошибка ловится до выполнения: не запускается весь файл, а не только эта строка.
quotes-inside.jsjs
// снаружи – другой вид кавычекconst ok1 = "д'Артаньян";// одинарные снаружи – двойные внутриconst ok2 = 'Он сказал: "да"';// или экранируем: черта делает кавычку текстомconst ok3 = 'д\'Артаньян';console.log(ok1);console.log(ok2);console.log(ok3);
Консоль
д'Артаньян
Он сказал: "да"
д'Артаньян

Экранирующие символы

Запись \' из примера выше – экранирующая последовательность: обратная косая черта и символ за ней читаются как одно целое. Черта отменяет привычную роль символа за ней: кавычка после черты – не граница строки, а обычный знак в тексте; буква n после черты – не буква, а перенос строки. Основных последовательностей четыре:

ЗаписьЧто даёт
\' или \"кавычка внутри строки
\\обратная косая черта
\nперенос строки
\tтабуляция

Склейка: + соединяет строки

Строки не складывают, а склеивают, и делает это знакомый по уроку «Числа и арифметика» +. Со строками у него другая работа: не считать, а соединять – слева направо и вплотную. Пробела между словами + не добавит: его пишут руками, внутри кавычек.

glue.jsjs
// пробел живёт внутри кавычекconsole.log('Привет, ' + 'мир');// сам + пробел не добавитconsole.log('Привет,' + 'мир');
Консоль
Привет, мир
Привет,мир

Смесь типов + тоже принимает, но по своему правилу: если хотя бы с одной стороны стоит строка, вторая сторона тоже станет строкой, и + склеит. Поэтому '7' + 1 – это не 8, а строка '71': единица превратилась в '1' и приклеилась к семёрке. Вся разница – в кавычках у семёрки; почему язык так делает, разберём в уроке «Преобразования типов».

glue-types.jsjs
// Счёт: 5 – число стало строкой и приклеилосьconsole.log('Счёт: ' + 5);// 71 – строка, а не 8console.log('7' + 1);// 8 – тут обе стороны числа: обычное сложениеconsole.log(1 + 7);
+ смотрит на типы: строка с чем угодно – склейка; два числа – сложение.

Порядок при этом обычный – слева направо. Поэтому в 1 + 2 + ' яблока' числа успевают сложиться до встречи со строкой: получится '3 яблока'. Но стоит строке оказаться первой – 'яблок: ' + 1 + 2 – и складывать уже нечего: каждое число по очереди приклеивается, выходит 'яблок: 12'.

glue-order.jsjs
// 3 яблока – числа успели сложитьсяconsole.log(1 + 2 + ' яблока');// яблок: 12 – строка первая, склейка с самого началаconsole.log('яблок: ' + 1 + 2);

Шаблонные литералы: окно в код

Склейка работает, но читается тяжело: чем больше кусочков, тем труднее собрать из них фразу глазами – кавычки, знаки + и пробелы вперемешку. Поэтому для сборки текста из значений есть третий вид кавычек – обратные (бэктики, клавиша ё).

Строка в бэктиках называется шаблонным литералом и умеет главное: вставлять значения прямо в текст через ${...}. Внутри ${...} можно написать любое выражение: имя переменной, вычисление или вызов функции. Сначала выражение вычислится, затем его результат попадёт в строку.

Всё внутри ${…} вычисляется, результат вклеивается в строку.
template.jsjs
const name = 'Ира';const apples = 3;// Привет, Ира! Яблок: 3console.log(`Привет, ${name}! Яблок: ${apples}`);// то же самое, собранное склейкойconsole.log('Привет, ' + name + '! Яблок: ' + apples);
Результат один и тот же. В шаблоне видна готовая фраза, в склейке – кусочки, кавычки и знаки + вперемешку.

Второе умение шаблонного литерала – многострочность: перенос строки пишется прямо в коде, между бэктиками, и попадает в текст как есть. Одинарные и двойные кавычки так не умеют – у них строка обязана закончиться на той же строке кода, а перенос внутри записывается только последовательностью \n.

multiline.jsjs
const receipt = `Чек №42Яблоки: 3 шт.Итого: 240 ₽`;// печатается в три строки – переносы попали в текстconsole.log(receipt);// SyntaxError: обычной кавычке нельзя на новую строку// const bad = 'Чек №42//              Яблоки...';
Переносы строк внутри бэктиков – часть текста, как их и написали.

Длина и первые методы

У строк есть встроенные умения – как log у console.

У каждой строки есть свойство .length – количество символов – и целый набор методов. toUpperCase() и toLowerCase() меняют регистр, includes('что') отвечает, есть ли внутри кусок текста, at(0) достаёт символ по номеру. Строки неизменяемы: методы не переписывают исходную строку. Результат зависит от метода: toUpperCase() возвращает новую строку, includes() – boolean, а at() – символ или undefined.

methods.jsjs
const word = 'JavaScript';console.log(word.length);  // 10// JAVASCRIPT – новая строкаconsole.log(word.toUpperCase());// true – boolean, не строкаconsole.log(word.includes('Java'));

Символы по номерам: [индекс]

К отдельному символу строки можно обратиться через квадратные скобки с номером: word[0]. Номер называется индексом, и отсчёт идёт с нуля: под нулём живёт первый символ, под единицей – второй, последний – под length - 1. Если символа с таким индексом нет, получится undefined.

п 0 р 1 и 2 в 3 е 4 т 5
index.jsjs
const word = 'привет';// 'п' – первый символ, индекс 0console.log(word[0]);// 'и' – третий: отсчёт с нуляconsole.log(word[2]);// 'т' – последний: длина 6, индексы 0..5console.log(word[5]);// undefined – такого индекса нетconsole.log(word[9]);

at(): символы с конца

Метод at() делает то же самое – word.at(0) вернёт первый символ. Его отличие (ES2022) – отрицательные индексы: они считают с конца, и at(-1) возвращает последний символ без вычисления длины. Квадратные скобки так не умеют: word[-1] даст undefined, а не последний символ.

at.jsjs
const word = 'привет';// 'п' – как word[0]console.log(word.at(0));// 'т' – последний, с концаconsole.log(word.at(-1));// undefined – скобки минусов не понимаютconsole.log(word[-1]);

Строку нельзя изменить изнутри

Индексы дают только чтение. Строки неизменяемы: создав строку, переписать её символы нельзя – попытка присвоить в word[0] молча не сработает, а в строгом режиме бросит ошибку. Любое «изменение» строки – это на самом деле новая строка: её кладут в переменную вместо старой.

immutable.jsjs
let word = 'кот';// попытка заменить первую буквуword[0] = 'К';console.log(word);
Консоль
кот
Ошибки нет, но и замены нет: строка осталась прежней.
new-string.jsjs
let word = 'кот';// новая строка в ту же переменную – так можноword = 'Кот';console.log(word);// метод тоже вернул НОВУЮ строкуconsole.log(word.toUpperCase());
Консоль
Кот
КОТ

// теперь вы знаете

  1. Строки создают в одинарных, двойных кавычках или бэктиках
  2. Строка кончается на первой же кавычке того же вида: внутрь берут другой вид или экранируют обратной косой чертой
  3. Экранирующие последовательности: \' и \" – кавычка, \\ – сама черта, \n – перенос строки, \t – табуляция
  4. + со строками склеивает: если с одной стороны строка, вторая тоже станет строкой, и '7' + 1 даёт '71'
  5. Бэктики дают подстановку значений через ${...} и многострочность; внутри ${...} – любое выражение
  6. Символы читают по индексу с нуля: word[0] или at(0); отрицательные индексы понимает только at
  7. Строки неизменяемы: символ не перезаписать, любое «изменение» – новая строка
  8. length, toUpperCase, toLowerCase, includes, at – базовый набор на каждый день

Проверьте себя

Что напечатает этот код?

console.log(`2 + 2 = ${2 + 2}`);

Чему равно 'привет'.length?

Что вернёт 'кот'.at(1)?

Что напечатает этот код?

console.log(1 + 2 + '5');

Выберите все корректные способы записать строку д'Артаньян.

Выбери все верные варианты

Что напечатает этот код?

console.log('C:\\photos');

Какая запись создаст строку из двух строк текста?

// запись 1
const a = `первая
вторая`;
// запись 2
const b = 'первая
вторая';
// запись 3
const c = 'первая' + 'вторая';
переключают уроки · не работают при фокусе в полях ввода