4. Основы JavaScript
4.8. Основы языка
Ядром любого языка является спецификация его работы на самом базовом уровне. Как правило, она определяет синтаксис, операторы, типы данных и встроенный функционал, на основе которых можно создавать сложные решения. В стандарте ЕСМА-262 все эти элементы определены для JavaScript в форме псевдоязыка, который называется ECMAScript. В большинстве веб-браузеров реализована версия ECMAScript из третьей редакции ЕСМА-262. На очереди пятая редакция, которая на конец 2011 года ни в одном браузере не реализована полностью. Сведения в этой главе основаны преимущественно на третьей редакции ECMAScript, а отличия пятой редакции описаны в выносках. 4.8.1. СинтаксисСинтаксис ECMAScript во многом похож на С (Си) и другие С-подобные языки, такие как Java и Perl. Если вы знакомы с ними, вам будет легко привыкнуть к более свободному синтаксису ECMAScript. Чувствительность к регистру.В ECMAScript все элементы, включая имена переменных, функций и операторов, чувствительны к регистру. Например, переменные test и Test различны, а ключевое слово typeof не может быть именем функции, тогда как typeOf – нормальное имя. Идентификаторы.Идентификатор (identifier) – это имя переменной, функции, свойства или аргумента функции. Идентификаторы могут состоять из одного или нескольких знаков, удовлетворяющих двум условиям:
В ECMAScript-идентификаторах применяется "верблюжья" нотация. Это означает, что первая буква является строчной, а первые буквы всех последующих слов – прописными, например: firstSecond
Хотя это не является требованием, рекомендуется следовать этому правилу, чтобы не отступать от формата встроенных функций и объектов ECMAScript. Ключевые слова, зарезервированные слова и значения true, false и null не могут быть идентификаторами. Комментарии.ECMAScript поддерживает однострочные и блочные комментарии в стиле С. Для ввода однострочного комментария используются две косые черты: // однострочный комментарий
Блочный комментарий начинается с косой черты и звездочки (/*), а заканчивается ими же в обратном порядке (*/): /* Это многострочный
Строгий режим.В ECMAScript 5 представлена концепция строгого режима (strict mode) – особой модели синтаксического анализа и выполнения JavaScript-кода, в которой исправлены некоторые неправильные аспекты работы ECMAScript и генерируются ошибки при небезопасных действиях. Чтобы включить строгий режим для всего сценария, добавьте в начало файла следующую команду: "use strict"
Хотя она выглядит как строка, которую забыли присвоить переменной, на самом деле это директива, переводящая JavaScript в строгий режим. Такой синтаксис был выбран специально, чтобы исключить конфликты с ECMAScript 3. Строгий режим можно включить и для отдельной функции, добавив эту директиву в начало тела функции: function doSomething() {
В строгом режиме выполнение JavaScript-кода заметно меняется, и мы не раз с этим столкнемся. Строгий режим поддерживается в Internet Explorer 10+, Firefox 4+, Safari 5.1+, Opera 12+ и Chrome. Инструкции.Инструкции в ECMAScript завершаются точками с запятой, хотя синтаксический анализатор сам способен определить конец инструкции, например: var sum = а + b // правильно даже без точки с запятой, но не рекомендуется
Хотя точки с запятой в конце инструкций необязательны, рекомендуется всегда добавлять их. Это предотвращает некоторые ошибки, например незавершенный ввод, и позволяет сжимать ECMAScript-код за счет удаления пустых мест (без точек с запятой это приводит к синтаксическим ошибкам). Кроме того, это препятствует снижению быстродействия, потому что синтаксические анализаторы пытаются исправлять предполагаемые ошибки, добавляя недостающие точки с запятой. Как и в С, при помощи фигурных скобок ({ }) несколько инструкций можно объединить в блок кода: if (test) {
В управляющих инструкциях вроде if блоки требуются, только если инструкций несколько, но на практике рекомендуется создавать блок даже для одной инструкции: if (test)
Использование блоков кода с управляющими инструкциями проясняет намерения программиста и предотвращает ошибки при изменении кода. Ключевые и зарезервированные слова.Стандарт ЕСМА-262 определяет набор ключевых слов (keywords), служащих для решения специализированных задач, таких как указание начала или конца управляющей инструкции или выполнение специфической операции. Ключевые слова нельзя использовать как идентификаторы или имена свойств. Вот их полный список (ключевое слово со звездочкой было добавлено в пятой редакции):
Кроме того, ЕСМА-262 содержит набор зарезервированных слов (reserved words), которые также нельзя использовать как идентификаторы или имена свойств. Хотя эти слова не имеют специфического применения в языке, они зарезервированы на будущее как потенциальные ключевые слова. Вот полный список зарезервированных слов из третьей редакции ЕСМА-262:
В пятой редакции список зарезервированных слов в нестрогом режиме сокращается до следующего:
В строгом режиме в пятой редакции в этот список добавляются следующие слова:
Обратите внимание, что слова let и yield были зарезервированы в пятой редакции, а все остальные – в третьей. Ради совместимости рекомендуется брать за ориентир список из третьей редакции, добавляя в него слова let и yield. Попытка использовать ключевое слово как имя идентификатора в реализациях ECMAScript 3 приводит к ошибке "Identifier Expected" (ожидается идентификатор). Применение зарезервированного слова с этой же целью в одних реализациях допускается, а в других приводит к ошибке. В пятой редакции немного изменены правила употребления ключевых и зарезервированных слов. Они по-прежнему не могут быть идентификаторами, но теперь их разрешено использовать как имена свойств в объектах. В общем, для обеспечения совместимости с прошлыми и будущими редакциями ECMAScript лучше не использовать ключевые и зарезервированные слова как идентификаторы и имена свойств. Кроме ключевых и зарезервированных слов в пятой редакции ЕСМА-262 налагаются ограничения на имена eval и arguments. В строгом режиме они не могут быть идентификаторами и именами свойств, иначе возникнет ошибка. Переменные.ECMAScript-переменные типизированы слабо, то есть могут содержать данные любого типа. Каждая переменная – это просто именованный заполнитель для значения. Для определения переменной используется оператор var (заметьте, что это одно из ключевых слов), после которого указывается имя (идентификатор) переменной, например: var message;
Здесь определяется переменная с именем message, которая может содержать любое значение (без инициализации она содержит специальное значение undefined, описанное в следующем разделе). ECMAScript поддерживает инициализацию переменных, то есть можно одновременно определить переменную и присвоить ей значение, например: var message = "hi";
Здесь определяется переменная message для хранения строки "hi". Инициализация не превращает переменную в строковую, она просто присваивает ей значение. После инициализации можно не только изменить хранящееся в переменной значение, но и тип этого значения, например:
var message = "hi";
В этом примере переменная message сначала определяется как строковое значение "hi", а затем перезаписывается числовым значением 100. Хотя изменять тип данных, содержащихся в переменной, не рекомендуется, в ECMAScript это возможно. Важно отметить, что при определении переменной с помощью оператора var она становится локальной в текущей области видимости. Например, если определить переменную с оператором var внутри функции, она будет уничтожена при выходе из функции:
function test () {
Здесь переменная message определяется с помощью оператора var в функции test (). При создании переменной ей присваивается значение, но сразу же после этого она уничтожается, из-за чего в последней строке возникает ошибка. Однако переменную можно определить глобально, просто опустив оператор var:
function test () {
Теперь переменная message определена как глобальная. При вызове функции test () она инициализируется и становится доступна вне функции. Определять глобальные переменные, опуская оператор var, не рекомендуется. Код с глобальными переменными, определенными локально, трудно разбирать и сопровождать, потому что непонятно, пропущен оператор var специально или случайно. В строгом режиме при попытке присвоить значение необъявленной переменной возникает ошибка ReferenceError. В одной инструкции можно определить сразу несколько переменных, разделив их (с инициализацией или без нее) запятыми:
var message = "hi",
Здесь объявляются и инициализируются три переменные. Поскольку ECMAScript типизирован слабо, в одной инструкции переменные можно инициализировать значениями разных типов. Чтобы облегчить чтение кода, можно разделить строку на несколько и добавить отступы, но это не требуется. В строгом режиме определить переменную с именем eval или arguments нельзя. Попытка сделать это приведет к синтаксической ошибке. 4.8.2. Типы данныхВ ECMAScript есть пять простых типов данных, также называемых примитивными типами (primitive types): неопределенный (undefined), нулевой (null), логический (boolean), числовой (number) и строковый (string). Есть также один сложный тип данных (object), который представляет собой неупорядоченный список пар имен и значений. Поскольку определить собственные типы данных в ECMAScript нельзя, все значения представляются с помощью одного из этих шести типов. Может показаться, что этого недостаточно, но у типов данных в ECMAScript есть динамические аспекты, благодаря которым каждый из них работает сразу за нескольких. Оператор typeof.Поскольку ECMAScript типизирован слабо, для работы с ним необходим какой-то способ определения типа данных переменной. Для получения этой информации можно применить к значению оператор typeof, который возвращает одну из следующих строк:
Оператор typeof вызывается следующим образом:
var message = "some string";
Здесь оператору typeof передаются переменная (message) и числовой литерал. Поскольку typeof – это оператор, а не функция, заключать операнды в скобки не требуется (хотя можно). Иногда typeof возвращает странные, но технически правильные значения. Так, typeof null возвращает строку "object", потому что специальное значение null считается ссылкой на пустой объект. В Safari до версии 5 (включительно) и Chrome до версии 7 (включительно) оператор typeof возвращает для регулярного выражения значение "function", а во всех остальных браузерах – "object". Тип undefined.Неопределенный тип (undefined) содержит единственное специальное значение undefined. Такое значение имеет переменная, объявленная с помощью оператора var, но не инициализированная:
var message;
Здесь переменная message объявляется без инициализации. Сравнение с литеральным значением undefined показывает, что они равны. Этот пример идентичен следующему:
var message = undefined;
Теперь переменная message явно инициализируется значением undefined, но это не требуется, потому что по умолчанию любая переменная без инициализации получает значение undefined. Тип null.Нулевой тип (null) также содержит единственный элемент – специальное значение null. Логически null – это указатель на пустой объект, поэтому оператор typeof возвращает для него строку "object":
var car = null;
При определении переменной, которая позднее будет содержать объект, рекомендуется инициализировать ее именно значением null. Это позволяет явно проверять, была ли назначена переменной ссылка на объект, например:
if (car != null) {
Значение undefined является производным от null, так что в ЕСМА-262 они определены как нестрого равные: alert (null == undefined); // true
При сравнении значений null и undefined с помощью оператора = = всегда возвращается true, но помните, что этот оператор преобразует свои операнды. Несмотря на то что значения null и undefined связаны, используются они поразному. Как уже отмечалось, никогда не следует явно присваивать переменной значение undefined, но к null это не относится. Каждый раз, когда нужный объект недоступен, вместо него следует использовать null. Это отражает тот факт, что значение null было введено как указатель на пустой объект, и подчеркивает его отличие от undefined. Тип boolean.Логический тип (boolean) – один из наиболее часто используемых в ECMAScript типов данных и имеет только два литеральных значения: true и false. Они отличаются от числовых значений: true не равно 1, a false не равно 0. Присвоить логические значения переменным можно следующим образом:
var found = true;
Имейте в виду, что литералы true и false чувствительны к регистру, так что True и False (и эти же слова с другими сочетаниями прописных и строчных букв) являются допустимыми идентификаторами, но не логическими значениями. Хотя литеральных логических значений всего два, в ECMAScript логические эквиваленты есть у всех значений. Для преобразования значения в его логический эквивалент используется специальная функция приведения типов bооlean ():
var message = "Hello world!";
В этом примере строка message преобразуется в логическое значение и сохраняется в переменной messageAsBoolean. Функция bоо1ean () может принимать и данные других типов, но всегда возвращает логическое значение. Правила преобразования значения в true или false зависят как от самого значения, так и от его типа (табл. 5).
Важно понимать эти преобразования, потому что управляющие инструкции вроде if выполняют их автоматически, например:
var message = "Hello world!";
В этом примере оповещение выводится на экран, потому что строка message автоматически преобразуется в логический эквивалент (true). Внимательно следите за тем, какие переменные используются в управляющих инструкциях. Ошибочное указание объекта вместо логического значения может радикально изменить логику приложения. Тип number.Пожалуй, наиболее интересным типом данных в ECMAScript является числовой (number). Он служит для представления целых чисел и чисел с плавающей точкой (которые в ряде языков называются числами с двойной точностью) в формате IEEE-754. Для поддержки чисел разных типов предусмотрено несколько разных форматов числовых литералов. Самый простой из них – формат десятичного числа, которое можно ввести непосредственно: var intNum = 55; // целое число
Целые числа также можно представлять как восьмеричные или шестнадцатеричные литералы. В восьмеричном литерале первой цифрой является нуль (0), за которым следует последовательность восьмеричных цифр (от 0 до 7). Если в литерале обнаруживается цифра не из этого диапазона, начальный нуль игнорируется и число интерпретируется как десятичное, например:
var octalNuml = 070; // 56 в восьмеричном формате
Числа, созданные в восьмеричном или шестнадцатеричном формате, во всех арифметических операциях используются как десятичные. Способ хранения чисел в JavaScript позволяет представить положительный нуль (+0) и отрицательный нуль (-0). Они всегда эквивалентны, но помечаются знаками для ясности. Значения с плавающей точкой.Чтобы определить значение с плавающей точкой, необходимо ввести десятичную точку и как минимум одну цифру после нее. Нуль перед десятичной точкой необязателен, но лучше его указывать. Вот некоторые примеры:
var floatNuml = 1.1;
Из-за того что для хранения значений с плавающей точкой требуется вдвое больше памяти, чем для целых чисел, ECMAScript по возможности преобразует значения в целые числа. Если после десятичной точки нет разрядов, число становится целым. Если значение не имеет дробной части (например, 1.0), оно также преобразуется в целое число. Тип string.Строковый тип (string) – это последовательности 16-разрядных знаков Юникода (в том числе пустые). Строки могут быть заключены в двойные (") или одинарные (') кавычки:
var firstName = "Nicholas";
В отличие от языка РНР, в котором интерпретация строки зависит от типа кавычек, в ECMAScript эти два варианта синтаксиса одинаковы, но кавычки в начале и конце строки не должны различаться. Например, такое выражение вызовет синтаксическую ошибку: var firstName = ’Nicholas"; // синтаксическая ошибка – разные кавычки
Тип Object.В ЕСМAScript объекты создаются как неспецифические сочетания данных и функциональности. Чтобы добавить в программу объект, нужно ввести оператор new и указать тип объекта. Для создания собственных объектов разработчики обычно создают экземпляры типа Object, а затем добавляют к ним свойства и (или) методы, например: var о = new Object ();
Этот синтаксис похож на Java, хотя в ECMAScript скобки нужны только при передаче аргументов в конструктор. Если аргументов нет, скобки можно опускать (однако это не рекомендуется): var о = new Object; // допустимо, но не рекомендуется
Сами по себе экземпляры типа Object не очень полезны, но важно понимать основы их работы, потому что подобно типу java.lang. Object в ECMAScript является родительским для всех остальных объектов. Все его свойства и методы есть у других, более специфичных объектов. Каждый экземпляр Object имеет свойства и методы из приведенного списка:
Поскольку тип Object является родительским для всех объектов в ECMAScript, эти базовые свойства и методы есть у каждого объекта. Технически принципы работы объектов в ЕСМА-262 относятся не ко всем объектам в JavaScript. Объекты в среде браузера, например ВОМ- и DOM-объекты, предоставляются и определяются средой. На них не распространяются требования ЕСМА-262, а потому они могут не наследоваться от типа Object. |
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||