Грамматика и типы

This article is in need of an editorial review.

В данной главе рассматриваются базовая грамматика, объявление переменных, типы данных и литералы.

Основы

JavaScript заимствует большую часть синтаксиса из Java, но также испытал влияние таких языков, как Awk, Perl и Python.

JavaScript чувствителен к регистру и использует Unicode.

В JavaScript инструкции называются statements и разделяются точкой с запятой (;). Пробел (space), табуляция (tab) и перевод строки (newline) называются пробельными символами (whitespace). Исходный текст скриптов на JavaScript сканируется слева направо и конвертируется в последовательность входных элементов, являющихся токенами (tokens), управляющими символами, символами конца строки, комментариями или пробельными символами. ECMAScript также определяет некоторые ключевые слова и литералы и устанавливает правила для автоматической вставки точек с запятой (ASI), чтобы обозначить конец инструкций (statements). Однако, рекомендуется всегда ставить точку с запятой в конце каждой инструкции вручную, чтобы избежать побочных эффектов. Чтобы получить более подробную информацию, прочитайте Lexical Grammar.

Комментарии

Синтаксис комментариев является таким же, как и в C++ и во многих других языках:

// Комментарий, занимающий одну строку.
 
/* Комментарий, 
   занимающий несколько строк.
 */
 
/* Нельзя вкладывать /* комментарии друг в друга */ SyntaxError */

Объявления

В JavaScript существует три вида объявлений:

var
Объявляет переменную, инициализация переменной значением является необязательной.
let
Объявляет локальную переменную в области видимости блока, инициализация переменной значением является необязательной.
const
Объявляет именованную константу, доступную только для чтения.

Переменные

Вы можете использовать переменные как символические имена для значений в вашем приложении. Имена переменных называются identifiers и должны соответствовать определенным правилам.

Идентификатор в JavaScript должен начинаться с буквы, нижнего подчеркивания (_) или знака доллара ($); последующие символы могут также быть цифрами (0-9). Поскольку JavaScript чувствителен к регистру, буквы включают символы от "A" до "Z" (верхний регистр) и символы от "a" до "z" (нижний регистр).

Вы можете использовать в идентификаторах буквы ISO 8859-1 или Unicode, например, å или ü. Вы также можете использовать управляющие последовательности Unicode как символы в идентификаторах.

Некоторые примеры корректных имен: Number_hitstemp99,  _name.

Объявление переменных

Вы можете объявить переменную тремя способами:

  • Используя ключевое слово var. Например, var x = 42. Данный синтаксис может быть использован для объявления как локальных, так и глобальных переменных.
  • Просто присвоить переменной значение. Например, x = 42. Переменные, объявленные данным способом, являются глобальными и не могут быть изменены на локальном уровне. Такое объявление генерирует исключение в строгом режиме (strict mode). Не рекомендуется использовать данный способ.
  • Используя ключевое слово let. Например, let y = 13. Данный синтаксис может быть использован для объявления локальной переменной в области видимости блока.

Вычисление переменных

Переменная, объявленная через var или let без присвоения начального значения, имеет значение undefined.

При попытке доступа к необъявленной переменной будет выброшено исключение ReferenceError:​

var a;
console.log("The value of a is " + a); // "The value of a is undefined"
console.log("The value of b is " + b); // ReferenceError

Вы можете использовать undefined, чтобы определить, имеет ли переменная значение. В следующем примере переменной input не присвоено значение, и оператор if будет вычислен как true:

var input;
if (input === undefined) {
  doThis();
} else {
  doThat();
}

Значение undefined ведет себя как false, когда используется в логическом контексте. Например, следующий код выполняет функцию myFunction, т.к. элемент myArray не определен:

var myArray = [];
if ( !myArray[0] ) myFunction();

Значение undefined конвертируется в NaN, когда используется в числовом контексте:

var a;
a + 2; // NaN

Значение null ведет себя как 0 в числовом контексте и как false в логическом контексте:

var n = null;
console.log(n * 32); // 0

Область видимости переменных

Когда вы объявляете переменную вне функции, то такая переменная называется глобальной переменной, т.к. доступна любому коду в текущем документе. Когда вы объявляете переменную внутри функции, то такая переменная называется локальной переменной, т.к. доступна только внутри данной функции.

До ECMAScript 6 в JavaScript отсутствовала область видимости блока; переменная, объявленная внутри блока, является локальной для функции (или глобальной области видимости), внутри которой находится данный блок. Например, следующий код выведет значение 5, т.к. областью видимости переменной x является функция (или глобальный контекст), внутри которой объявлена переменная x, а не блок, которым в данном случае является оператор if:

if (true) {
  var x = 5;
}
console.log(x); // 5

Такое поведение меняется, если используется оператор let, введенный в ECMAScript 6:

if (true) {
  let y = 5;
}
console.log(y); // ReferenceError

Поднятие переменных

Другим необычным свойством переменных в JavaScript является то, что можно сослаться на переменную, которая объявляется позже, и не получить при этом исключения. Эта концепция известна как поднятие (hoisting) переменных; переменные в JavaScript поднимаются в самое начало функции или выражения. Однако, переменные, которые еще не были инициализированы, возвратят значение undefined:

/*
 * Example 1
*/

console.log(x === undefined); // true
var x = 3;

/*
 * Example 2
*/

var myvar = "my value";
 
(function() {
  console.log(myvar); // undefined
  var myvar = "local value";
})();

Приведенные выше примеры будут интерпретироваться так же, как:

/*
 * Example 1
*/

var x;
console.log(x === undefined); // true
x = 3;
 
/*
 * Example 2
*/

var myvar = "my value";
 
(function() {
  var myvar;
  console.log(myvar); // undefined
  myvar = "local value";
})();

Из-за поднятия переменных, все операторы var в функции следует размещать настолько близко к началу функции, насколько это возможно. Следование этому правилу улучшает ясность кода.

Глобальные переменные

Глобальные переменные на самом деле являются свойствами глобального объекта. На веб-страницах глобальным объектом является window, поэтому вы можете устанавливать глобальные переменные и обращаться к ним, используя синтаксис window.variable:

window.foo = 'bar';

Следовательно, вы можете обращаться к глобальным переменным, объявленным в одном объекте window или frame из другого объекта window или frame, указав имя window или frame. Например, если переменная phoneNumber объявлена в документе, то вы можете сослаться на эту переменную из iframe как parent.phoneNumber.

Константы

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

const prefix = '212';

Нельзя изменить значение константы через присваивание или повторное объявление во время выполнения скрипта. Значение должно быть указано при инициализации.

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

Нельзя объявить константу с таким же именем, как у функции или переменной в одной области видимости. Следующие примеры выбросят исключение TypeError:

function f() {}
const f = 5;
function f() {
  const g = 5;
  var g;
}

Структуры и типы данных

Типы данных

Последний стандарт ECMAScript определяет семь типов данных:

  • Шесть типов данных,  которые являются примитивами:
    • Booleantrue и false.
    • null. Специальное ключевое слово, обозначающее нулевое или «пустое» значение. Поскольку JavaScript чувствителен к регистру, null не то же самое, что Null, NULL или любой другой вариант.
    • undefined. Свойство глобального объекта; переменная, не имеющая присвоенного значения, обладает типом undefined.
    • Number42 или 3.14159.
    • String. "Howdy".
    • Symbol (ECMAScript 6)
  • и Object

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

Преобразование типов данных

JavaScript — это динамически типизированный язык. Это означает, что вам не нужно указывать тип данных переменной, когда вы ее объявляете, типы данных преобразуются автоматически по мере необходимости во время выполнения скрипта. Так, например, вы можете определить переменную следующим образом:

var answer = 42;

А позже вы можете присвоить этой переменной строковое значение, например:

answer = "Thanks for all the fish...";

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

В выражениях, включающих числовые и строковые значения с оператором +, JavaScript преобразует числовые значения в строковые. Например:

x = "The answer is " + 42 // "The answer is 42"
y = 42 + " is the answer" // "42 is the answer"

В выражениях с другими операторами JavaScript не преобразует числовые значения в строковые. Например:

"37" - 7 // 30
"37" + 7 // "377"

Преобразование строк в числа

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

parseInt преобразует строку в целочисленное значение. Хорошей практикой является всегда указывать основание системы счисления (параметр radix).

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

"1.1" + "1.1"       // "1.11.1"
(+"1.1") + (+"1.1") // 2.2
// Обратите внимание на то, что скобки не являются обязательными и используются для ясности.

Литералы

Литералы используются для представления значений в JavaScript. Они являются фиксированными значениями, а не переменными. В данной секции рассматриваются следующие типы литералов:

Литерал array

Литерал array — это список из нуля или более выражений, каждое из которых представляет элемент массива, заключенный в квадратные скобки ( [] ). Когда вы создаете массив, используя литерал array, он инициализируется с помощью переданных значений, которые будут являться его элементами, длина массива будет равна числу переданных аргументов.

В следующем примере создается массив coffees с тремя элементам и длиной, равной трем:

var coffees = ["French Roast", "Colombian", "Kona"];
coffees.length; // 3

Обратите внимание на то, что литерал array является инициализатором объекта. Чтобы получить более подробную информацию, прочитайте Использование инициализаторов объекта.

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

Литералы array также являются объектами Array. Чтобы получить более подробную информацию, прочитайте Array и Indexed collections.

Лишние запятые в литералах array

Не обязательно указывать все элементы в литерале array. Если вы поставите две запятые подряд, то пропущенные элементы будут иметь значение undefined. Например:

var fish = ["Lion", , "Angel"]; // ["Lion", undefined, "Angel"]

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

var myList = ['home', , 'school', ]; // ["home", undefined, "school"]
myList.length;                       // 3

В следующем примере длина массива равна четырем, элементы myList[0] и myList[2] имеют значение undefined:

var myList = [ , 'home', , 'school']; // [undefined, "home", undefined, "school"]

В следующем примере длина массива равна четырем, элементы myList[1] и myList[3] имеют значение undefined. Игнорируется только последняя запятая.

var myList = ['home', , 'school', , ]; // ["home", undefined, "school", undefined]

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

Литерал boolean

Логический (Boolean) тип имеет два литеральных значения: true и false.

Не путайте примитивные логические значения true и false со значениями true и false объекта Boolean. Объект Boolean является объектом-обёрткой над примитивом логического типа. Чтобы получить более подробную информацию, прочитайте Boolean.

Литерал integer

Целые числа могут быть записаны в десятичной, шестнадцатеричной, восьмеричной и двоичной системах счисления.

  • Десятичный целочисленный литерал состоит из последовательности цифр без ведущего нуля.
  • Ведущий ноль в целочисленном литерале указывает на то, что он записан в восьмеричной системе счисления. Восьмеричные целые числа состоят только из цифр 0-7.
  • Ведущие символы 0x (или 0X) указывают на то, что число шестнадцатеричное. Шестнадцатеричные целые числа могут состоять из цифр 0-9 и букв a-f и A-F. 

Несколько примеров целочисленных литералов:

0, 117 и -345 (десятичная система счисления)
015, 0001 и -077 (восьмеричная система счисления) 
0x1123, 0x00111 и -0xF1A7 (шестнадцатеричная система счисления)

Литерал floating-point

Числа с плавающей точкой могут состоять из следующих частей:

  • Десятичное целое число, которое может иметь знак (символ "+" или "-", стоящий перед числом),
  • Десятичная точка ("."),
  • Дробная часть (другое десятичное число),
  • Экспонента.

Экспонента состоит из символа "e" или "E", за которым следует целое число, которое может иметь знак. Число с плавающей точкой должно состоять по крайней мере из одной цифры и либо десятичной точки, либо символа "e" (или "E").

Несколько примеров чисел с плавающей точкой: 3.1415, -3.1E12, .1e12, 2E-12.

В более сжатой форме синтаксис выглядит следующим образом:

[(+|-)][digits][.digits][(E|e)[(+|-)]digits]

Примеры:

3.14
2345.789
.3333333333333333333
-.283185307179586

Литерал object

Литерал object — это список из нуля или более пар, состоящих из имен свойств и связанных с ними значений, заключенный в фигурные скобки ( {} ). Вам не следует использовать литерал object в начале выражения, т.к. это приведет к ошибке или к поведению, которого вы не ожидаете, потому что символ "{" будет интерпретироваться как начало блока.

В следующем примере свойству myCar объекта car присваивается строка "Saturn", свойству getCar — результат вызова функции CarTypes("Honda"), свойству special — значение переменной Sales:

var Sales = "Toyota";

function CarTypes(name) {
  if (name == "Honda") {
    return name;
  } else {
    return "Sorry, we don't sell " + name + ".";
  }
}

var car = { myCar: "Saturn", getCar: CarTypes("Honda"), special: Sales };

console.log(car.myCar);   // Saturn
console.log(car.getCar);  // Honda
console.log(car.special); // Toyota

Кроме того, вы можете использовать числовой или строковой литералы в именах свойств или вкладывать один объект в другой. Например:

var car = { manyCars: {a: "Saab", "b": "Jeep"}, 7: "Mazda" };

console.log(car.manyCars.b); // Jeep
console.log(car[7]);         // Mazda

Именем свойства объекта может быть любая строка, в том числе пустая строка. Если имя свойства не является корректным JavaScript идентификатором, то оно должно быть заключено в кавычки. Для обращения к таким именам следует использовать квадратные скобки ( [] ), а не точку ( . ):

var unusualPropertyNames = {
  "": "An empty string",
  "!": "Bang!"
}
console.log(unusualPropertyNames."");   // SyntaxError: Unexpected string
console.log(unusualPropertyNames[""]);  // "An empty string"
console.log(unusualPropertyNames.!);    // SyntaxError: Unexpected token !
console.log(unusualPropertyNames["!"]); // "Bang!"

Обратите внимание на следующий пример:

var foo = {a: "alpha", 2: "two"};
console.log(foo.a);               // alpha
console.log(foo[2]);              // two
// console.log(foo.2);            // SyntaxError: Unexpected number
// console.log(foo[a]);           // ReferenceError: a is not defined
console.log(foo["a"]);            // alpha
console.log(foo["2"]);            // two

Литерал string

Литерал string — это ноль или более символов, заключенных в двойные ( " ) или одинарные ( ' ) кавычки. Строка должна быть ограничена кавычками одного типа, т.е. либо обе одинарные, либо обе двойные. Например:

  • "foo"
  • 'bar'
  • "1234"
  • "one line \n another line"
  • "John's cat"

Вы можете вызвать любой из методов объекта String для строкового литерала: JavaScript автоматически преобразует строковой литерал во временный объект String, вызовет метод, а затем уничтожит временный объект String. Вы также можете использовать свойство String.length со строковым литералом:

console.log("John's cat".length);
// Число символов в строке, включая пробел.
// В данном случае длина строки равна 10.

Вам следует использовать строковые литералы до тех пор, пока вам специально не понадобится объект String. Чтобы получить более подробную информацию об объекте String, прочитайте String.

Использование специальных символов в строках

Кроме обычных символов вы также можете включать специальные символы в строки. Например:

"one line \n another line"

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

Специальные символы в JavaScript
Символ Значение
\b Возврат (Backspace)
\f Перевод или прогон страницы (Form feed)
\n Перевод строки (New line)
\r Возврат каретки (Carriage return)
\t Табуляция (Tab)
\v Вертикальная табуляция (Vertical tab)
\' Апостроф или одинарная кавычка
\" Двойная кавычка
\\ Обратная косая черта (Backslash)
\XXX

Символ в кодировке Latin-1, представленный тремя восьмеричными числами XXX от 0 до 377. Например, \251 (символ ©).

\xXX

Символ в кодировке Latin-1, представленный двумя шестнадцатеричными числами XX от 00 до FF. Например, \xA9 (символ ©).

\uXXXX

Символ в Unicode, представленный четырьмя шестнадцатеричными числами XXXX. Например, \u00A9 (символ ©).

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

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

Вы можете вставить кавычку в строку, если поставите перед ней обратную косую черту. Это называется экранированием кавычек. Например:

var quote = "He read \"The Cremation of Sam McGee\" by R.W. Service.";
console.log(quote); // He read "The Cremation of Sam McGee" by R.W. Service.

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

var home = "c:\\temp"; // c:\temp

Вы также можете экранировать перевод строки. Обратная косая черта и перевод строки будут удалены из содержимого строки. Например:

var str = "this string \
is broken \
across multiple\
lines."
console.log(str); // this string is broken across multiplelines.

Хотя JavaScript не поддерживает синтаксис "heredoc", но вы можете эмулировать его, добавив перевод строки и обратную косую черту в конец каждой строки:

var poem = 
"Roses are red,\n\
Violets are blue.\n\
I'm schizophrenic,\n\
And so am I."

Дополнительная информация

Данная глава фокусируется на базовом синтаксисе для объявлений и типов. Чтобы получить более подробную информацию о конструкциях JavaScript, прочитайте:

В следующей главе рассматриваются управляющие конструкции и обработка ошибок.

Метки документа и участники

Метки: 
Обновлялась последний раз: fscholz,
Скрыть боковую панель