Лексична граматика

Ця стаття описує лексичну граматику JavaScript. Текст коду скриптів ECMAScript сканується зліва направо та перетворюється на послідовність вхідних елементів, якими є токени, керівні символи, символи розриву рядка, коментарі або пробільні символи. ECMAScript також визначає певні ключові слова та має правила для автоматичної вставки крапки з комою для завершення інструкцій.

Керівні символи

Керівні символи не мають візуального відображення, але використовуються для керування інтерпретацією тексту.

Керівні символи Юнікоду
Код символа Назва Скорочення Опис
U+200C Роз'єднувач нульової ширини
(Zero width non-joiner)
<ZWNJ> Розташовується між символами, щоб запобігти об'єднанню їх у лігатури у певних мовах (Вікіпедія).
U+200D Об'єднувач нульової ширини
(Zero width joiner)
<ZWJ> Розташовується між символами, які інакше не були б об'єднані, щоб відобразити символи у їхній об'єднаній формі у певних мовах (Вікіпедія).
U+FEFF Маркер порядку байтів
(Byte order mark)
<BOM> Використовується на початку скрипта, щоб позначити його як Юнікод, та для позначення порядку байтів (Вікіпедія).

Пробільні символи

Пробільні символи покращують читабельність тексту коду та відділяють токени один від одного. Ці символи зазвичай не є обов'язковими для функціональності коду. Часто використовують інструменти мініфікації для прибирання пробільних символів, щоб зменшити кількість даних, які необхідно передати.

Пробільні символи
Код символа Назва Скорочення Опис Екранована послідовність
U+0009 Табуляція символа
(Character tabulation)
<HT> Горизонтальна табуляція \t
U+000B Табуляція рядка
(Line tabulation)
<VT> Вертикальна табуляція \v
U+000C Зміна сторінки
(Form feed)
<FF> Керівний символ розриву сторінки (Вікіпедія). \f
U+0020 Пробіл
(Space)
<SP> Звичайний пробіл
U+00A0 Нерозривний пробіл
(No-break space)
<NBSP> Звичайний пробіл, але відсутня позиція, де можливий розрив рядка
Інші Інші пробільні символи Юнікоду <USP> Пробіли Юнікоду на Вікіпедії

Символи розриву рядка

На додачу до пробільних символів, символи розриву рядка використовуються для покращення читабельності тексту коду. Однак, у деяких випадках символи розриву рядка можуть вплинути на виконання коду JavaScript, оскільки існують декілька місць, де вони заборонені. Символи розриву рядка також впливають на процес автоматичної вставки крапки з комою. Символи розриву рядка відповідають класу \s у регулярних виразах.

Лише наступні коди символів Юнікоду сприймаються як символи розриву рядка у ECMAScript, інші символи розриву сприймаються як пробільні (наприклад, символ Наступний рядок (Next Line), NEL, U+0085 вважається пробільним символом).

Символи розриву рядка
Код символа Назва Скорочення Опис Екранована послідовність
U+000A Зміна рядка
(Line Feed)
<LF> Символ нового рядка в системах UNIX. \n
U+000D Повернення каретки
(Carriage Return)
<CR> Символ нового рядка у Commodore та ранній системі Mac. \r
U+2028 Роздільник рядків
(Line Separator)
<LS> Вікіпедія
U+2029 Роздільник абзаців
(Paragraph Separator)
<PS> Вікіпедія

Коментарі

Коментарі використовуються для додавання приміток, зауваг, пропозицій чи застережень до коду JavaScript. Це робить код легшим для читання та розуміння. Їх також можна використовувати для відключення коду, щоб запобігти його виконанню; це може бути цінним інструментом відлагодження.

JavaScript має два давніх способи додавання коментарів у код.

Перший - це коментарі //; він перетворює весь текст, що розташований за ним, на коментар. Наприклад:

function comment() {
  // Це однорядковий коментар JavaScript
  console.log('Всім привіт!');
}
comment();

Другий спосіб - це стиль /* */, він набагато гнучкіший.

Наприклад, ви можете використати його на одному єдиному рядку:

function comment() {
  /* Це однорядковий коментар JavaScript */
  console.log('Всім привіт!');
}
comment();

Ви також можете створювати багаторядкові коментарі, ось так:

function comment() {
  /* Цей коментар містить декілька рядків. Зауважте,
     що коментар не потрібно завершувати, поки ми не закінчили. */
  console.log('Всім привіт!');
}
comment();

Ви також можете за бажанням використати його всередині рядка, хоча це може зробити ваш код важчим для читання, тому його варто використовувати з обережністю:

function comment(x) {
  console.log('Всім ' + x /* вставити значення x */ + ' !');
}
comment('привіт');

На додачу, ви можете відключити код, щоб уникнути його виконання, огорнувши код ось так:

function comment() {
  /* console.log('Всім привіт!'); */
}
comment();

У цьому випадку виклик console.log() не виконується, оскільки знаходиться всередині коментаря. Таким чином можна відключити будь-яку кількість рядків коду.

Коментарі шебанг

Спеціалізований третій синтаксис коментарів, коментар шебанг, знаходиться в процесі стандартизації у ECMAScript (дивіться Hashbang Grammar proposal).

Коментар шебанг поводиться так само, як однорядковий коментар (//). Але він починається з позначки #! та дозволений лише на самому початку тексту скрипта. Також зауважте, що перед позначкою #! не можна ставити жодних пробільних знаків. Коментар складається з усіх символів, що стоять після #! до самого кінця першого рядка; дозволений лише один такий коментар.

Коментар шебанг визначає шлях до специфічного інтерпретатора JavaScript, який ви бажаєте використати для виконання скрипта. Приклад виглядає наступним чином:

#!/usr/bin/env node

console.log("Всім привіт");

Заувага: Коментарі шебанг у JavaScript імітують шебанги в Unix, що використовуються для запуску файлів з відповідним інтерпретатором.

Хоча символ BOM перед коментарем шебанг працює у переглядачі, його не радять використовувати у скрипті з шебангом. BOM не працюватиме, якщо ви намагаєтесь виконати скрипт у Unix/Linux. Тому використовуйте UTF-8 без символа BOM, якщо ви хочете виконувати скрипти безпосередньо з оболонки.

Стиль коментарів #! має використовуватись тільки для того, щоб вказати інтерпретатор JavaScript. У всіх інших випадках просто ставте коментар // (чи багаторядковий коментар).

Ключові слова

Зарезервовані ключові слова у ECMAScript 2015

Ключові слова, зарезервовані на майбутнє

Наступні слова зарезервовані як ключові слова специфікацією ECMAScript. Наразі вони не мають спеціальної функціональності, але невдовзі, можливо, матимуть, тому їх не можна використовувати в якості ідентифікаторів.

Наступні слова завжди зарезервовані:

  • enum

Наступні слова є зарезервованими лише у строгому режимі:

  • implements
  • interface
  • let
  • package
  • private
  • protected
  • public
  • static

Наступні є зарезервованими лише у коді модулів:

  • await

Ключові слова, зарезервовані на майбутнє у старших стандартах

Далі наведено ключові слова, зарезервовані на майбутнє старшими специфікаціями ECMAScript (ECMAScript від 1 до 3).

  • abstract
  • boolean
  • byte
  • char
  • double
  • final
  • float
  • goto
  • int
  • long
  • native
  • short
  • synchronized
  • throws
  • transient
  • volatile

Крім того, літерали null, true та false не можна використовувати в якості ідентифікаторів у ECMAScript.

Використання зарезервованого слова

Зарезервовані слова, насправді, стосуються лише ідентифікаторів (на противагу іменам ідентифікаторів). Як описано у es5.github.com/#A.1, це усі імена ідентифікаторів, які не включають зарезервовані слова.

a.import
a['import']
a = { import: 'test' }.

З іншого боку, наступний код є некоректним, тому що це ідентифікатор, ними є імена ідентифікаторів без зарезервованих слів. Ідентифікатори використовуються для оголошення функцій, функціональних виразів, оголошення змінних і т.д. Імена ідентифікаторів використовуються для виразу елемента (MemberExpression), виразу виклику (CallExpression) і т.д.

function import() {} // некоректно.

Ідентифікатори зі спеціальними значеннями

Декілька ідентифікаторів мають спеціальні значення у певному контексті, не будучи ключовими словами жодного виду. Ними є:

Літерали

Літерал null

Додаткову інформацію дивіться також у null.

null

Булевий літерал

Дивіться також додаткову інформацію у Boolean.

true
false

Числові літерали

Типи Number та BigInt використовують числові літерали.

Десятковий

1234567890
42

// Будьте обережні при використанні нуля попереду
0888 // 888 розбирається як десяткове
0777 // розбирається як вісімкове, 511 у десятковій системі

Зауважте, що десяткові літерали можуть починатися з нуля (0), за яким іде інша десяткова цифра, але, якщо усі цифри після 0 менші за 8, число інтерпретується як вісімкове. Це не спричинить викидання помилки у JavaScript, дивіться помилку 957513. Також дивіться статтю щодо parseInt()

Експоненціальний

Десятковий експоненціальний літерал позначається наступним форматом: beN; де b - мантиса (число, ціле чи з рухомою комою), далі символ e (який слугує роздільником, або експоненціальним показником) та N, яке вказує порядок – ціле число зі знаком (згідно з 2019 ECMA-262): 

0e-5   // => 0
0e+5   // => 0
5e1    // => 50
175e-2 // => 1.75
1e3    // => 1000
1e-3   // => 0.001

Двійковий

Синтаксис двійкових чисел використовує нуль на початку, за яким іде латинська літера "B", маленька чи велика (0b або 0B). Оскільки цей синтаксис новий у ECMAScript 2015, дивіться таблицю сумісності з веб-переглядачами, наведену нижче. Якщо цифри після 0b не є 0 чи 1, викидається наступна помилка SyntaxError: "Missing binary digits after 0b".

var FLT_SIGNBIT  = 0b10000000000000000000000000000000; // 2147483648
var FLT_EXPONENT = 0b01111111100000000000000000000000; // 2139095040
var FLT_MANTISSA = 0B00000000011111111111111111111111; // 8388607

Вісімковий

Синтаксис вісімкових чисел використовує нуль на початку, за яким іде латинська літера "O", маленька чи велика (0o або 0O). Оскільки цей синтаксис новий у ECMAScript 2015, дивіться таблицю сумісності з веб-переглядачами, наведену нижче. Якщо цифри після 0o виходять за межі діапазону (01234567), викидається наступна помилка SyntaxError: "Missing octal digits after 0o".

var n = 0O755; // 493
var m = 0o644; // 420

// Також можна просто через нуль на початку 
// (дивіться заувагу щодо десяткових чисел вище)
0755
0644

Шістнадцятковий

Синтаксис шістнадцяткових чисел використовує нуль на початку, за яким іде латинська літера "X", велика чи маленька (0x або 0X). Якщо цифри після 0x виходять за межі діапазону (0123456789ABCDEF), викидається наступна помилка SyntaxError: "Identifier starts immediately after numeric literal".

0xFFFFFFFFFFFFFFFFF // 295147905179352830000
0x123456789ABCDEF   // 81985529216486900
0XA                 // 10

Літерал BigInt

Тип BigInt є числовим простим типом у JavaScript, який може представляти цілі числа з довільною точністю. Літерали BigInt створюються додаванням n в кінець цілого числа.

123456789123456789n     // 123456789123456789
0o777777777777n         // 68719476735
0x123456789ABCDEFn      // 81985529216486895‬
0b11101001010101010101n // 955733

Зауважте, що старі вісімкові числа з просто нулем на початку не працюватимуть з BigInt:

// 0755n
// SyntaxError: invalid BigInt syntax

Для вісімкових чисел BigInt завжди використовуйте нуль з літерою "o" (великою чи маленькою):

0o755n

Більше інформації щодо BigInt дивіться у статті Структури даних JavaScript.

Числові роздільники

Щоб покращити читабельність числових літералів, можна використовувати підкреслення (_, U+005F) в якості роздільників:

// роздільники у десяткових числах
1_000_000_000_000
1_050.95

// роздільники у двійкових числах
0b1010_0001_1000_0101

// роздільники у вісімкових числах
0o2_2_5_6

// роздільники у шістнадцяткових числах
0xA0_B0_C0

// роздільники у BigInt
1_000_000_000_000_000_000_000n

Зверніть увагу на ці обмеження:

// Не можна ставити більше одного підкреслення підряд
100__000; // SyntaxError

// Не можна ставити в кінці числового літерала
100_; // SyntaxError

// Не можна використовувати після нуля на початку 0
0_1; // SyntaxError

Об'єктні літерали

Більше інформації дивіться також на сторінках Object та Ініціалізатор об'єкта.

var o = { a: 'foo', b: 'bar', c: 42 };

// скорочений запис. Нове у ES2015
var a = 'foo', b = 'bar', c = 42;
var o = {a, b, c};

// замість
var o = { a: a, b: b, c: c };

Масивні літерали

Більше інформації дивіться також у Array.

[1954, 1974, 1990, 2014]

Рядкові літерали

Рядковий літерал - це нуль чи більше кодів символів Юнікоду всередині одинарних або подвійних лапок. Коди символів Юнікоду також можуть бути представлені екранованими послідовностями. Усі коди символів можуть з'являтись безпосередньо у рядковому літералі, окрім цих закриваючих кодів символів:

  • U+005C \ (зворотній слеш),
  • U+000D <CR>
  • та U+000A <LF>.

До появи пропозиції зробити весь текст формату JSON дозволеним у ECMA-262, неекрановані U+2028 <LS> та U+2029 <PS> також були заборонені у рядкових літералах.

Будь-які коди символів можуть з'являтись у вигляді екранованої послідовності. Рядкові літерали повертають значення ECMAScript String. Під час генерування цих значень String коди символів Юнікоду кодуються форматом UTF-16.

'foo'
"bar"

Шістнадцяткові екрановані послідовності

Шістнадцяткові екрановані послідовності складаються з \x та рівно двох шістнадцяткових символів, що відображають кодову одиницю чи код символа у діапазоні від 0x0000 до 0x00FF.

'\xA9' // "©"

Екрановані послідовності Юнікоду

Екранована послідовність Юнікоду складається рівно з чотирьох шістнадцяткових символів, записаних після \u. Вона відображає кодову одиницю у кодуванні UTF-16. Для кодів символів від U+0000 до U+FFFF кодова одиниця дорівнює коду символа. Коди символів від U+10000 до U+10FFFF потребують двох екранованих послідовностей, які відображають дві кодові одиниці (сурогатну пару), що використовуються для кодування символа; сурогатна пара відрізняється від коду символа.

Дивіться також String.fromCharCode() та String.prototype.charCodeAt().

'\u00A9' // "©" (U+A9)

Екранування кодів символів Юнікоду

Екранування коду символа Юнікоду складається з \u{, далі код символа у шістнадцятковому форматі, за ним }. Значення шістнадцяткових символів має знаходитись в діапазоні між 0 та 0x10FFFF включно. Коди символів у діапазоні від U+10000 до U+10FFFF не потребують представлення у вигляді сурогатної пари. Екранування кодів символів було додане у JavaScript у ECMAScript 2015 (ES6).

Дивіться також String.fromCodePoint() та String.prototype.codePointAt().

'\u{2F804}' // CJK COMPATIBILITY IDEOGRAPH-2F804 (U+2F804)

// той самий символ у вигляді сурогатної пари
'\uD87E\uDC04'

Літерал регулярного виразу

Більше інформації дивіться також у RegExp.

/ab+c/g

// Літерал "порожнього" регулярного виразу
// Порожня група необхідна,
// щоб уникнути неоднозначності щодо однорядкових коментарів.
/(?:)/

Шаблонні літерали

Дивіться також шаблонні рядки.

`текстовий рядок`

`текстовий рядок 1
 текстовий рядок 2`

`текст ${вираз} текст`

тег `текст ${вираз} текст`

Автоматична вставка крапки з комою

Деякі інструкції JavaScript повинні завершуватись крапкою з комою, і тому підпадають під автоматичну вставку крапки з комою (ASI, automatic semicolon insertion):

  • Порожній оператор
  • let, const, інструкція змінної
  • import, export, оголошення модуля
  • Інструкція виразу
  • debugger
  • continue, break, throw
  • return

Специфікація ECMAScript визначає три правила вставки крапки з комою.

1. Крапка з комою вставляється перед, коли символ розриву рядка чи "}" вважається таким, що недозволений за синтаксисом.

{ 1 2 } 3 

// перетворюється на 

{ 1 2 ;} 3;

2. Крапка з комою вставляється в кінці, коли виявлено кінець вхідного набору токенів, але синтаксичний аналізатор неспроможний розібрати єдиний вхідний набір як завершену програму.

Тут ++ не сприймається як постфіксний оператор, що застосовується до змінної b, тому що між b та ++ знаходиться символ розриву рядка.

a = b
++c

// перетворюється на

a = b;
++c;

3. Крапка з комою вставляється в кінці, коли інструкція з обмеженими граматичними застосуваннями супроводжується символом розриву рядка. Ці інструкції з правилом "жодних розривів рядка в цьому місці" наступні:

  • Постфіксні вирази (++ та --)
  • continue
  • break
  • return
  • yield, yield*
  • module
return
a + b

// перетворюється на

return;
a + b;

Специфікації

Специфікація
ECMAScript (ECMA-262)
The definition of 'Lexical Grammar' in that specification.

Сумісність з веб-переглядачами

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidFirefox for AndroidOpera for AndroidSafari on iOSSamsung InternetNode.js
Array literals ([1, 2, 3])Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 4Opera Full support 4Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Binary numeric literals (0b)Chrome Full support 41Edge Full support 12Firefox Full support 25IE No support NoOpera Full support 28Safari Full support 9WebView Android Full support 41Chrome Android Full support 41Firefox Android Full support 25Opera Android Full support 28Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Full support 4.0.0
Full support 0.12
Disabled
Disabled From version 0.12: this feature is behind the --harmony runtime flag.
Boolean literals (true/false)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support 3Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Decimal numeric literals (1234567890)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support 3Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Hashbang (#!) comment syntax
Experimental
Chrome Full support 74Edge Full support 79Firefox Full support 67IE No support NoOpera Full support 62Safari No support NoWebView Android Full support 74Chrome Android Full support 74Firefox Android Full support 67Opera Android Full support 53Safari iOS No support NoSamsung Internet Android No support Nonodejs Full support 0.1.100
Hexadecimal escape sequences ('\0xA9')Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 4Opera Full support 4Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Hexadecimal numeric literals (0xAF)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support 3Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Null literal (null)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support 3Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Numeric separators (1_000_000_000_000)Chrome Full support 75Edge Full support 79Firefox Full support 70IE No support NoOpera Full support 62Safari Full support 13WebView Android Full support 75Chrome Android Full support 75Firefox Android No support NoOpera Android No support NoSafari iOS Full support 13Samsung Internet Android No support Nonodejs Full support 12.5.0
Full support 12.5.0
Full support 10.4.0
Disabled
Disabled From version 10.4.0: this feature is behind the --harmony runtime flag.
Octal numeric literals (0o)Chrome Full support 41Edge Full support 12Firefox Full support 25IE No support NoOpera Full support 28Safari Full support 9WebView Android Full support 41Chrome Android Full support 41Firefox Android Full support 25Opera Android Full support 28Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Full support 4.0.0
Full support 0.12
Disabled
Disabled From version 0.12: this feature is behind the --harmony runtime flag.
Regular expression literals (/ab+c/g)Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 4Opera Full support 5Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
String literals ('Hello world')Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 3Opera Full support 3Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Unicode escape sequences ('\u00A9')Chrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 4Opera Full support 4Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100
Unicode point escapes (\u{})Chrome Full support 44Edge Full support 12Firefox Full support 40IE No support NoOpera Full support 31Safari Full support 9WebView Android Full support 44Chrome Android Full support 44Firefox Android Full support 40Opera Android Full support 32Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Shorthand notation for object literalsChrome Full support 43Edge Full support 12Firefox Full support 33IE No support NoOpera Full support 30Safari Full support 9WebView Android Full support 43Chrome Android Full support 43Firefox Android Full support 33Opera Android Full support 30Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Template literalsChrome Full support 41Edge Full support 12Firefox Full support 34IE No support NoOpera Full support 28Safari Full support 9WebView Android Full support 41Chrome Android Full support 41Firefox Android Full support 34Opera Android Full support 28Safari iOS Full support 9Samsung Internet Android Full support 4.0nodejs Full support 4.0.0
Trailing commasChrome Full support 1Edge Full support 12Firefox Full support 1IE Full support 9Opera Full support 9.5Safari Full support 1WebView Android Full support 1Chrome Android Full support 18Firefox Android Full support 4Opera Android Full support 10.1Safari iOS Full support 1Samsung Internet Android Full support 1.0nodejs Full support 0.1.100

Legend

Full support  
Full support
No support  
No support
Experimental. Expect behavior to change in the future.
Experimental. Expect behavior to change in the future.
User must explicitly enable this feature.
User must explicitly enable this feature.

Хід реалізації

Наведена нижче таблиця надає щоденний статус реалізації цієї функціональності, оскільки функціональність ще не досягла кросбраузерної стабільності. Дані генеруються запуском відповідних тестів функціональності у Test262, стандартному тестовому наборі JavaScript, на нічній збірці чи на останньому релізі рушія JavaScript кожного веб-переглядача.

Див. також