Язык возник на основе нескольких технологий, самыми известными из которых являются языки JavaScript и JScript. Разработка первой редакции спецификации началась в ноябре 1996 года. Принятие спецификации состоялось в июне 1997 года. Будучи отправленной в ISO/IEC JTC 1 для принятия по процедуре Fast-Tracking, она послужила основой международного стандарта ISO/IEC 16262. В июне 1998 года общим собранием ECMA была принята вторая редакция ECMA-262, соответствующая ISO/IEC 16262. Третья редакция спецификации отличалась от предыдущей введением поддержки регулярных выражений, улучшением поддержки строк, введением новых управляющих конструкций, механизма исключений, форматирования при численном вводе и некоторыми другими изменениями[Спецификация 2].
Числовой тип данных в ECMAScript соответствует 64-битному формату чисел с плавающей запятой, определённому стандартом IEEE 754-2008 за исключением того, что различные значения Not-a-Number, определяемые в стандарте[4], представляются в данном языке единственным специальным значением NaN[Спецификация 4].
Нулевой и неопределённый типы данных Дэвидом Флэнаганом неформально причисляются к «тривиальным» типам, поскольку каждый из них определяет только одно значение[5].
Помимо перечисленных восьми типов данных, в ECMAScript имеется поддержка[Спецификация 5] ещё ряда типов, используемых для хранения промежуточных результатов вычисляемых выражений.
Популярность языка JavaScript и нетривиальность обработки данных, относящихся к разным типам, обусловили развёртывание академических исследований в области анализа типов данных ECMAScript, ставящих своей целью создание полноценного анализатора кода, который можно было бы применять в интегрированных средах разработки[6].
Инструкции
В ECMAScript имеется пятнадцать различных видов инструкций, данные о которых представлены в таблице ниже:
while (<инструкция>) <выражение>
for ([<инструкция до начала>]; [<инструкция>]; [<инструкция>]) <выражение>
for (<объявление переменных>; [<инструкция>]; [<инструкция>]) <выражение>
for (<lvalue-выражение> in <инструкция>) <выражение>
for (<объявление переменных> in <инструкция>) <выражение>
Несмотря на обязательность точки с запятой в случаях, отмеченных в четвёртой колонке, спецификация декларирует механизм автодополнения строк точками с запятой, приводящий к тому, что при наличии переноса строки инструкция до переноса может быть снабжена этим знаком[Спецификация 7], что является объектом критики[7].
Инструкции, меняющие смысл при использовании перевода строки внутри[Спецификация 7]
Унарный постфиксный ++
Унарный постфиксный --
Продолжение
Прерывание
Возврат
Генерация исключения
Пример изменения смысла инструкции
return{status:"complete"};
Здесь выделенная строка содержит допустимую языком инструкцию и, поскольку далее следует перевод строки, срабатывает механизм автодополнения строк точками с запятой. Вместо того, чтобы функция, содержащая приведённый код, в качестве своего значения вернула объект со свойством status, она вернёт undefined.
Несмотря на то, что литеральная форма записи объекта блоком кода не является, единообразие в расстановке скобок может приводить к ошибкам. Снизить вероятность их появления способна выработка или принятие подходящего стандарта оформления кода. Играет роль выбор стиля отступов. В частности, стили Олмана и Уайтсмита, а также стиль Хорстмана и стиль GNU для кода JavaScript не рекомендуются к использованию большинством руководств[8] в отличие от стилей K&R, 1TBS, BSD KNF.
Несрабатывание механизма автодополнения
В случае, если выражение, записанное на следующей строке, синтаксически может быть продолжением выражения на предыдущей строке, механизм автодополнения строк точками с запятой не срабатывает[9].
В данном примере квадратные скобки на второй строке интерпретируются в качестве обращения к элементу массива, возвращаемого func(). Запятая в скобках трактуется как соответствующий оператор, возвращающий 'h2'. Таким образом, код преобразуется к следующему:
Ещё одной особенностью ECMAScript по отношению к другим C-подобным языкам является то, что в данном языке блоки не образуют области видимости. Объявленные в блоке переменные распространяются на всю функцию, содержащую блок[10][11].
В данном участке кода имеет место повторное объявление переменной в выделенных строках:
Кроме того, к переменной tmp, объявленной внутри первого из циклов (строка 4), в соответствии с синтаксисом языка вполне законно обратиться извне цикла (строка 10).
Переменные определяются с помощью ключевых слов var, let, const. При объявлении переменная помещается в область видимости, соответствующую в случае var функции, а в случае let, const блоку кода. Если переменная объявляется вне функций, она помещается в глобальную область видимости. Создание переменной происходит при получении управления функцией с её объявлением. Или программой, если переменная глобальна. При создании переменной в ECMAScript она приобретает значение undefined. Если переменная объявлена с инициализацией, инициализация происходит не в момент создания переменной, а при выполнении строки с инструкцией var[Спецификация 9].
При раскомментировании выделенной строки на экран будет выводиться не number, а undefined:
vara=42;functionfoo(){alert(typeofa);// var a = 10;}foo();
При создании переменной она приобретает внутреннее свойство {DontDelete} и её невозможно удалить с помощью оператора delete[Спецификация 9]. Исключение составляют переменные, объявленные в контексте eval[12][Спецификация 10].
Многие источники[13][14][15][16][17][18] декларируют возможность неявного объявления переменных в ECMAScript при осуществлении присваивания корректному идентификатору, не являющемуся формальным аргументом функции, без предварительного объявления с помощью var. Однако в терминологии спецификации языка в этом случае создаётся свойство глобального объекта, а не переменная[12][Спецификация 9].
Фиксация в стандарте оформления кода необходимости обязательного объявления переменных до их использования[Стандарты кодирования 1][Стандарты кодирования 4] (либо фиксация необходимости использовать пространства имён для всех глобальных объектов[Стандарты кодирования 2]) позволяет избегать трудноуловимых ошибок, предотвращая опасность взаимодействия одинаково названных переменных в разных участках кода[19].
Ключевые и зарезервированные слова
Следующие слова являются ключевыми в языке и не могут быть использованы как идентификаторы[Спецификация 11]:
break do instanceof typeof
case else new var
catch finally return void
continue for switch while
debugger function this with
default if throw
delete in try
По сравнению с третьей редакцией спецификации[Спецификация 12] в пятой добавилось ключевое слово debugger с соответствующей инструкцией.
Следующие слова используются как ключевые слова в предложенных расширениях и поэтому являются зарезервированными для возможности адаптировать эти расширения[Спецификация 13]:
class enum extends super
const export import
При использовании строгого режима следующие слова рассматриваются как зарезервированные для использования в будущем[Спецификация 13]:
implements let private public yield
interface package protected static
Таким образом, по сравнению с третьей редакцией спецификации языка количество зарезервированных для использования в будущем слов существенно снизилось. Ранее их было 31[Спецификация 14], и наличие большого количества ключевых и зарезервированных слов, большинство из которых не используется в языке, подвергалось критике[20].
Операторы
В ECMAScript имеются как операторы, использующие в качестве названий ключевые слова, так и операторы, использующие в качестве названий знаки препинания.
Классификация операторов
По убыванию приоритета операторы ECMAScript можно разбить в следующие группы:
. (доступ к свойству),[] (доступ к свойству),() (вызов функции), new (создание нового объекта);
Операторы ++, --, -, +, ~, !, delete, typeof, void, ?:, =, *=, /=, +=, -=, <<=, >=, >>>=, &=, ^=, |= правоассоциативны (то есть для них a op b op c эквивалентно a op (b op c)). Остальные операторы ECMAScript левоассоциативны[22].
По арности операторы ECMAScript делятся на следующие группы:
операторы, не имеющие фиксированного количества операндов (())[24].
По положению знака операции относительно операндов операторы ECMAScript делятся на следующие группы:
префиксные (например, new, ++ (префиксный инкремент);
инфиксные (например, +, -);
постфиксные (например, ++ (постфиксный инкремент), -- (постфиксный декремент).
Также операторы классифицируются по типу операндов[25] и по характеру осуществляемого действия.
Особенности операторов ECMAScript
В ECMAScript нет оператора, позволяющего проверить, относится ли свойство непосредственно к объекту или является унаследованным. Такая проверка осуществляется с помощью метода hasOwnProperty(). В связи с тем, что данный метод не является оператором, он может быть переписан любым другим свойством[26].
Оператор + является единственным арифметическим оператором в языке, который перегружен для строковых аргументов. Если хотя бы один из операндов — строка, + действует как конкатенатор, в противном случае выполняется сложение[27][Спецификация 16].
В отличие от языков, где void является типом данных, в ECMAScript это оператор, возвращающий значение undefined[28].
Оператор == осуществляет проверку на равенство по алгоритму, состоящему из 10 шагов, подразумевающему в ряде случаев преобразование типов[Спецификация 17], что, в конечном счёте, может привести к неочевидным результатам[29].
Пример результатов работы == (во всех перечисленных случаях значением оператора === с теми же аргументами будет false):
Функции в ECMAScript являются объектами[30][31]. Конструктор, с помощью которого они создаются — Function(). Функции, как и любые другие объекты, могут храниться в переменных, объектах и массивах, могут передаваться как аргументы в другие функции и могут возвращаться функциями. Функции, как и любые другие объекты, могут иметь свойства. Существенной специфической чертой функций является то, что они могут быть вызваны[30].
Задание функций
В ECMAScript имеется два типа функций:
внутренние функции (например, parseInt),
функции, определённые в тексте программы.
Внутренние функции представляют собой встроенные объекты (см. ниже), не обязательно реализованные на ECMAScript[Спецификация 18].
В тексте программы именованную функцию в ECMAScript можно определить одним из следующих способов:
// объявление функцииfunctionsum(arg1,arg2){returnarg1+arg2;}// задание функции с помощью инструкцииvarsum2=function(arg1,arg2){returnarg1+arg2;};// задание функции с использованием объектной формы записиvarsum3=newFunction("arg1","arg2","return arg1 + arg2;");
Последний способ наименее предпочтителен, поскольку де-факто сводится к заданию функции с помощью выражения, но при этом порождает двойную интерпретацию кода (дополнительная интерпретация возникает при передаче кода в конструктор), что может негативно отразиться на производительности[31].
Первые два способа дают похожий, но не идентичный эффект. Усугубляет ситуацию то, что инструкция, использующаяся при задании функции, может выглядеть очень похоже на объявление функции: во-первых, за ключевым словом function может следовать идентификатор[Спецификация 19], во-вторых, точка с запятой может быть опущена в силу механизма автодополнения строк точками с запятой[Спецификация 7].
Пример:
// объявление функцииfunctionsum(arg1,arg2){returnarg1+arg2;}// задание функции с помощью выраженияvarsum2=functionsum(arg1,arg2){returnarg1+arg2;}functionbar(){};// использование объявления функции(functionbar(){})// использование соответствующей инструкции
Наиболее существенной разницей между заданием функции с использованием объявления и заданием функции с помощью выражения является то, что в первом случае создание переменной и присваивание ей в качестве значения функции осуществляются до выполнения кода при входе в контекст исполнения. Во втором случае переменная получает значение инициализатора при выполнении оператора присваивания. При создании же переменной, осуществляемом при входе в контекст исполнения, она инициализируется значением undefined[Спецификация 20][32] (подробнее см. в разделе Объявление переменных).
Пример, иллюстрирующий разницу в порядке выполнения кода:
alert(sum(3,4));// 7: переменная sum к моменту выполнения этой строки уже создана и в качестве значения ей присвоена функцияfunctionsum(arg1,arg2){returnarg1+arg2;}alert(sum2(3,4));// ошибка: переменная sum2 к моменту выполнения этой строки уже создана, но в качестве значения ей присвоено undefinedvarsum2=function(arg1,arg2){returnarg1+arg2;};
Объявлением функций не следует пользоваться внутри условных конструкций[33], хотя в Gecko-браузерах это обработается интуитивным образом за счёт реализованного механизма функций как инструкций[34].
Присваивания функций
Поскольку функции в ECMAScript являются объектами, то есть относятся к ссылочному типу данных, идентификаторы функций являются переменными, хранящими ссылку на функцию. Проиллюстрировать это можно следующим кодом:
В выделенной строке следует обратить внимание на отсутствие оператора вызова функции (()) в правой части присваивания. Если бы в этой строке вместо sum было указано sum(), переменной sum2 присвоилась бы не функция, а результат её вызова. Ещё внимания заслуживает то, что после присваивания sum2 указывает не на копию функции, а на ту самую функцию, на которую указывает sum.
Перегрузка функций
В ECMAScript перегрузка функций не относится к свойствам языка, а её эффект обеспечивается за счёт использования других механизмов.
Пример, показывающий отсутствие перегрузки функций:
Если объявлено несколько функций с одинаковыми названиями, более поздние объявления перезаписывают ранние объявления[31].
Тем не менее, эффект перегрузки функций достижим.
1. Проверка на undefined.
Для того, чтобы проверить, передан ли в функцию фактический аргумент, можно осуществить проверку формального аргумента на идентичность значению undefined. Например:
2. Проверка типа.
Кроме того, typeof, instanceof, constructor могут быть использованы для выяснения типа фактических аргументов и кастомизации поведения функции в зависимости от них.
3. Обращение к данным об аргументах.
В функциях ECMAScript можно получить доступ к данным об аргументах с помощью объекта arguments[Спецификация 21]. Он, в частности, позволяет воспользоваться индексированием для доступа к конкретным переданным аргументам[31][35] и свойством length, хранящем количество фактически переданных аргументов, что может быть полезно при применении парадигмы обобщённого программирования.
Функции ECMAScript допускают рекурсивный вызов. При задании функции с помощью инструкции без указания идентификатора после ключевого слова function внутри функции можно обратиться к ней с помощью свойства callee объекта arguments[Спецификация 21].
В ECMAScript функция представляет собой объект первого класса и может быть передана в другую функцию как аргумент. Если она при этом вызывается в функции, в которую передаётся, то её называют функцией обратного вызова (или callback-функцией). Если при этом передаваемая функция не имеет имени, это анонимная функция обратного вызова (анонимная callback-функция)[36]. Основные причины использования функций обратного вызова:
избежание именования функции при оперировании с ней (способствует снижению числа глобальных переменных)[36],
делегирование вызова функции другой функции (способствует повышению выразительности кода)[36],
Функциям в ECMAScript присуща лексическая область видимости. Это означает, что область видимости определяется в момент определения функции (в отличие от динамической области видимости, при которой область видимости определяется в момент вызова функции)[38].
При объявлении функции последовательность областей видимости, относящихся ко вложенным функциям, сохраняется как составляющая состояния функции. То есть в процессе выполнения программы функции, обладающие доступом к локальным переменным объемлющих функций, сохраняют такой доступ на протяжении всего выполнения программы[38].
Механизм замыканий может использоваться для ограничения видимости переменных автономного участка программы с тем, чтобы не возникали конфликты имён при совместном с другим кодом использовании. Для этого код помещается в анонимную функцию, снабжаемую оператором вызова функции.
(function(){// Участок программы, доступ к переменным которого необходимо изолировать извне.})();
При этом определённые в участке программы функции становятся вложенными по отношению к добавленной анонимной функции и в них возможно осуществление доступа к локальным переменным анонимной функции (которые до её введения были глобальными). Однако извне анонимной функции доступ к ним осуществить нельзя: результат выполнения функции игнорируется.
Замыкания используются не только для запрещения доступа к ряду переменных, но и к модификации такого доступа. Это достигается с помощью функций, возвращающих другие функции.
Пример функции-генератора последовательных чисел:
Синтаксис и функциональность регулярных выражений в ECMAScript сформировались под влиянием Perl 5[Спецификация 22] и допускают два вида синтаксиса: литеральный и объектный.
В первом случае шаблон (pattern) и флаги (flags) указываются явно, не сопровождаясь дополнительными избыточными синтаксическими знаками: их разделителями служат слеши. Во втором случае шаблон и флаги должны представлять собой переменные, содержащие строковые значения, либо непосредственно строковые значения. Литеральная форма записи предпочтительнее тем, что не требует двойного[~ 2]экранирования метасимволов регулярных выражений, в отличие от объектной формы[41].
В качестве флагов в ECMAScript могут использоваться следующие символы:
глобальный режим: шаблон применяется ко всем соответствиям в строке, работа регулярного выражения не останавливается после первого найденного соответствия шаблону
i
игнорирование регистра: при поиске соответствий регистр символов шаблона и строки игнорируются
m
многострочный режим: строка, содержащая символы перевода строки, трактуется как несколько строк, разделённых символами перевода строки; работа регулярного выражения осуществляется во всех строках
Каждое регулярное выражение представляет собой объект со следующими свойствами:
соответствует номеру позиции в строке, в которой обнаружилось совпадение с шаблоном в результате предыдущего применения регулярного выражения или 0, если регулярное выражение ранее не применялось
формирует массив подстрок, соответствующих заданному шаблону с учётом выставленных флагов. null, если никакая подстрока не соответствует шаблону
test(handledString)
логический
true, если нашлась строка, соответствующая шаблону и false в противном случае
Объекты
Реализация в языке
Объекты ECMAScript представляют собой неупорядоченные коллекциисвойств, каждое из которых имеет один или более атрибутов, которые определяют, как может быть использовано свойство — например, если в качестве значения атрибута ReadOnly установлена истина, то любая попытка выполняющегося ECMAScript-кода поменять значение этого свойства останется безрезультатной. Свойства представляют собой контейнеры, инкапсулирующие другие объекты, значения примитивных типов и методы[Спецификация 23].
Свойство является свойством только для чтения. Попытка поменять значение этого свойства, предпринятая в программе, останется безрезультатной. В некоторых случаях значение свойства с установленным атрибутом ReadOnly меняется в силу действий среды расширения языка, поэтому ReadOnly не следует понимать как неизменное
DontEnum
Свойство не перечисляется циклом for-in
DontDelete
Попытки удалить это свойство будут проигнорированы
Internal
Свойство является внутренним. Оно не имеет названия и к нему нельзя получить доступ с помощью аксессоров. Доступ к этим свойствам определяется реализацией языка.
Объекты ECMAScript подразделяются на базовые (native) и объекты расширения (host). Под базовыми понимаются любые объекты, независимые от окружения, относящегося к расширению языка. Некоторые из базовых объектов являются встроенными (built-in): существующими с самого начала выполнения программы. Другие могут быть созданы, когда программа выполняется. Объекты расширения предоставляются расширением ECMAScript, а для ECMAScript это значит, что они входят в объектную модель документа или в объектную модель браузера[Спецификация 3].
Синтаксис
Для задания объектов может использоваться объектная и литеральная формы. Объектная форма задания объекта имеет синтаксис, аналогичный Java, но, в отличие от него, скобки в ECMAScript требуется использовать только при передаче аргументов в конструктор[42]. Синтаксически следующие записи эквивалентны:
varobj1=newObject();varobj2=newObject;varobj3={};
Однако второй вариант использовать не рекомендуется[42]. Дуглас Крокфорд рекомендует избегать и первого варианта, отдавая предпочтение литеральной форме, которую он считает большим достоинством языка[43].
Спецификация языка оперирует понятием свойства объекта, называя методом использующуюся в качестве свойства объекта функцию[Спецификация 3].
Функция, использованная для создания объекта (в примерах выше это Object())
hasOwnProperty(propertyName)
Показывает, существует ли данное свойство в объекте (не в его прототипе)
isPrototypeOf(object)
Определяет, находится ли объект в цепи прототипов объекта-аргумента
propertyIsEnumerable(propertyName)
Показывает, является ли свойство с данным названием перечислимым в цикле for-in
toString()
Возвращает представление объекта в виде строки
valueOf()
Возвращает значение this. Если же объект является результатом вызова конструктора объекта расширения, значение valueOf() зависит от реализации[Спецификация 25]. Зачастую в качестве возвращаемого значения выступает значение примитивного типа, соответствующее объекту. Как правило, результат данного метода совпадает с результатом toString(). Объекты, созданные с помощью конструктора Date() — яркий пример, где результаты toString() и valueOf() не совпадают[42].
Доступ к свойствам объекта осуществляется использованием точечной и скобочной записи:
varobj=newObject();alert(obj.constructor===obj["constructor"]);// true — использование точечной и скобочной записи для доступа к свойствуvarfoo=obj["toString"];// использование скобочной записи для сохранения функции в переменнуюvarresult=obj["toString"]();// сохранение результата вызова функции в переменнуюalert(foo());// вывод на экран результата вызова сохранённой функцииalert(result);varboo=obj.toString;// аналогично с использованием точечной записиvarres=obj.toString();alert(boo());alert(res);
Задание новых свойств может осуществляться динамически.
varcountry=newObject();country["name"]="Russia";// использование скобочной записиcountry.foundationYear=862;// использование точечной записиvarcountry2={"name":"Russia","foundationYear":862};// использование литеральной формы
Подходы к созданию объектов
Создание объектов описанным в предыдущем разделе способом может быть непрактичным из-за необходимости дублировать код[44]. Если в программе происходит манипуляция с большим количеством однотипных объектов, разработчик имеет возможность выбрать одну из используемых в языке техник[44]:
фабрика объектов
функция, создающая объект и возвращающая его в качестве своего значения,
функция, использующая ключевое слово this для формирования свойств объекта, создаваемого ей с помощью оператора new,
прототипный подход
задействование свойства prototype функции для вынесения общих свойств объектов,
смешанный подход конструктор-прототип
использование конструктора для задания свойств объектов, не являющихся методами и прототипного подхода — для задания методов,
метод динамического прототипа
заключение кода, относящегося к функции создания объектов на основе смешанного подхода конструктор-прототип, в неё одну с обеспечением однократности присваивания свойств прототипа,
метод паразитического конструктора
использование new с функцией фабрики объектов.
В языке нет классов, однако их можно эмулировать за счёт использования конструкторов. Пример эмуляции класса в ECMAScript:
Для каждой из составляющих объекта можно рассматривать наследование. При наследовании интерфейса родителя без того, чтобы потомок использовал функциональность предка, говорят о наследовании интерфейса.
При наследовании состояния осуществляется наследование объектом-потомком структуры данных объекта-предка.
При наследовании функциональности речь идёт о наследовании вместе с интерфейсом и кода методов. Как правило, это влечёт необходимость организации наследования состояния, что делает разумным объединение наследования состояния и наследования функциональности в наследование реализации[45].
В отношении ECMAScript неприменимо лишь наследование интерфейсов, поскольку функции в языке не имеют сигнатур[44].
О возможностях, предоставляемых языком для организации наследования, можно судить, например, по приводимому[46]Стояном Стефановым списку из двенадцати разных способов организации наследования.
ECMAScript 6
Принятие ES6 устранило многие классы проблем JavaScript[47][48][49][50].
↑Aiken A., Applegate M., Bailey D. and others.6.2. Operations with NaNs // IEEE Standard for Floating-Point Arithmetic / Chair Zuras D., Editor Cowlishaw M. — USA, 2008. — P. 34. — ISBN 978-0-7381-5753-5.
↑Jensen S., Møller A., Thiemann P.Type Analysis for JavaScript (англ.) // Lecture Notes in Computer Science : Материалы конф. / The 16th International Static Analysis Symposium (SAS 2009), Лос-Анджелес, США, 9 – 11 августа 2009. — Springer Berlin / Heidelberg, 2009. — Vol. 5673. — P. 238 — 255. — ISBN 978-3-642-03236-3. (недоступная ссылка)
↑Crockford D.A.3. Semicolon Insertion // JavaScript: The Good Parts. — 2008. — P. 102. — ISBN 978-0-596-51774-8.
↑Keith J.Variables // DOM Scripting: Web Design with JavaScript and the Document Object Model. — 1st ed. — USA: Wordware Publishing, Inc, 2005. — 18 — 20 p. — ISBN 1590595335.
↑Koch Peter-Paul.Chapter 5. Core. Section D. Variables // ppk on JavaScript / Editor: Wendy Sharp. — 1st ed. — New Riders Press, 2006. — 528 p. — ISBN 978-0-321-42330-6.
↑Crockford D.A.4. Reserved Words // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8.
↑Juriy "kangax" Zaytsev.Named function expressions demystified(англ.). — Статья, детально описывающая разницу между заданием функции с помощью объявления и заданием функции с помощью выражения. Дата обращения: 19 октября 2009. Архивировано из оригинала 19 июня 2009 года.
↑Maian и др.Conditionally defining a function(англ.). Functions and function scope. — Описание деталей реализации функций как выражений в контексте объявлений внутри условий. Дата обращения: 19 октября 2009. Архивировано из оригинала 14 октября 2008 года.
↑Crockford D.4.4. Arguments // JavaScript: The Good Parts. — 2008. — P. 31. — ISBN 978-0-596-51774-8.
↑ 1234Stefanov S.Callback Functions // Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and libraries. — 1st ed. — Packt Publishing, 2008. — P. 73, 74. — ISBN 184719414.
↑Crockford D.4.11. Callbacks // JavaScript: The Good Parts. — 2008. — P. 40. — ISBN 978-0-596-51774-8.
↑Одним обратным слешем экранируются метасимволы строк (например, \t). Для экранирования метасимволов регулярных выражений используется двойной обратный слеш (например, \\s)
↑ 12JavaScript Code Conventions(англ.). Echo Web Framework. NextApp, Inc. — Стандарт оформления кода JavaScript, принятый для Echo Web Framework. Дата обращения: 5 октября 2009. Архивировано 18 февраля 2012 года.
↑ 123Komenda, Klaus.JavaScript Coding Guidelines and Standards(англ.). Сайт австрийского веб-разработчика Клауса Коменда. — Стандарт оформления кода JavaScript Клауса Коменда. Дата обращения: 5 октября 2009. Архивировано 18 февраля 2012 года.
↑JavaScript coding style(англ.). GNOME. — Стандарт оформления кода JavaScript в GNOME. Дата обращения: 24 декабря 2009. Архивировано 18 февраля 2012 года.