ECMAScript

Материал из Seo Wiki - Поисковая Оптимизация и Программирование
Перейти к навигацииПерейти к поиску
ECMAScript
Класс языка:

мультипарадигменный: объектно-ориентированное, обобщённое, функциональное, императивное, аспектно-ориентированное, событийно-ориентированное, прототипное программирование

Появился в:

1995 г.

Автор(ы):

Брендан Айх

Типизация данных:

утиная

Диалекты:

JavaScript, JScript, ActionScript, JScript .NET

Испытал влияние:

Self, Си, Scheme, Perl, Python, Java

Повлиял на:

Objective-J

ECMAScript — это встраиваемый расширяемый не имеющий средств ввода/вывода язык программирования, используемый в качестве основы для построения других скриптовых языков[1]. Стандартизирован международной организацией ECMA в спецификации ECMA-262. Расширения языка, JavaScript, JScript и ActionScript, широко используются в вебе.

История

Язык возник на основе нескольких технологий, самыми известными из которых являются языки JavaScript и JScript. Разработка первой редакции спецификации началась в ноябре 1996 года. Принятие спецификации состоялось в июне 1997 года. Будучи отправленной в ISO/IEC JTC 1 для принятия по процедуре Fast-Tracking, она послужила основой международного стандарта ISO/IEC 16262. В июне 1998 года общим собранием ECMA была принята вторая редакция ECMA-262, соответствующая ISO/IEC 16262. Третья редакция спецификации отличалась от предыдущей введением поддержки регулярных выражений, улучшением поддержки строк, введением новых управляющих конструкций, механизма исключений, форматирования при численном вводе и некоторые другие изменения[Спецификация 1].

Семантика и синтаксис

Типы данных

Примитивные типы данных
Примитивные типы данных

В ECMAScript поддерживаются пять примитивных типов данных:

Числовой тип данных в ECMAScript соответствует 64-битному формату чисел с плавающей запятой, определённому стандартом IEEE 754-2008 за исключением того, что различные значения Not-a-Number, определяемые в стандарте[2], представляются в данном языке единственным специальным значением NaN[Спецификация 3].

Нулевой и неопределённый типы данных Дэвидом Флэнаганом неформально причисляются к тривиальным типам, поскольку каждый из них определяет только одно значение[3].

Также в языке имеется составной тип данных[3]:

Помимо перечисленных шести типов данных в ECMAScript имеется поддержка ещё семи, используемых исключительно для хранения промежуточных результатов вычисляемых выражений:

Популярность языка JavaScript и нетривиальность обработки данных, относящихся к разным типам, обусловили развёртывание академических исследований в области анализа типов данных ECMAScript, ставящих своей целью создание полноценного анализатора кода, который можно было бы применять в интегрированных средах разработки[4].

Инструкции

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

Типы инструкций, определяемые спецификацией языка[Спецификация 6]
Название Оригинальное название Краткие сведения Завершающая ;[Спецификация 7]
Блок Block {[<инструкции>]} -
Объявление переменной VariableStatement var <список объявления переменных> +
Пустая инструкция EmptyStatement ; +
Выражение ExpressionStatement [строка до ∉ {{, function}] инструкция +
Условие IfStatement if (<инструкция>) <выражение>[ else <выражение>] -
Цикл IterationStatement do <выражение> while (<инструкция>)

while (<инструкция>) <выражение>
for ([<инструкция до начала>]; [<инструкция>]; [<инструкция>]) <выражение>
for (<объявление переменных>; [<инструкция>]; [<инструкция>]) <выражение>
for (<lvalue-выражение> in <инструкция>) <выражение>
for (<объявление переменных> in <инструкция>) <выражение>

+/-[~ 1]
Продолжение ContinueStatement continue [<идентификатор>] +
Прерывание BreakStatement break [<идентификатор>] +
Возврат ReturnStatement return [<инструкция>] +
Сочетание WithStatement with (<инструкция>) <выражение> -
Метка LabelledStatement <идентификатор>: <выражение> -
Выбор SwitchStatement switch (<инструкция>) case <инструкция>: [<выражения>][ case <инструкция>: [<выражения>] …] [default: [<выражения>]] -
Генерация исключения ThrowStatement throw <инструкция> +
Блок try TryStatement try <блок> catch (<идентификатор>) <блок>
try <блок> finally <блок>
try <блок> catch (<идентификатор>) <блок> finally <блок>
-
(новое[Спецификация 8]) Отладчик Debugger debugger -

Автодополнение строк точками с запятой

Несмотря на обязательность точки с запятой в случаях, отмеченных в четвёртой колонке, спецификация декларирует механизм автодополнения строк точками с запятой, приводящий к тому, что при наличии переноса строки инструкция до переноса может быть снабжена этим знаком[Спецификация 7], что является объектом критики[5].

Инструкции, меняющие смысл при использования перевода строки внутри[Спецификация 7]

  • Унарный постфиксный ++
  • Унарный постфиксный --
  • Продолжение
  • Прерывание
  • Возврат
  • Генерация исключения

Пример изменения смысла инструкции <source lang="javascript" highlight="1"> return {

   status: "complete"

}; </source>

Здесь выделенная строка содержит допустимую языком инструкцию и, поскольку, далее следует перевод строки, срабатывает механизм автодополнения строк точками с запятой. Вместо того, чтобы в качестве своего значения функция, содержащая приведённый код, в качестве своего значения вернула объект со свойством status, она вернёт undefined.

Учёт этой особенности языка при выработке стандарта оформления кода может помочь избежать ошибок. Играет роль выбор стиля отступов. В частности, широко распространённые сейчас стили Олмана и Уайтсмита, а также стиль Хорстмана и стиль GNU для кода JavaScript являются менее предпочтимыми, нежели стили K&R, 1TBS, BSD KNF или баннерный стиль.

В стандартах кодирования принято прописывать обязательность проставления точек с запятой даже в тех случаях, когда синтаксис языка позволяет их опускать[Стандарты кодирования 1][Стандарты кодирования 2][Стандарты кодирования 3][Стандарты кодирования 4][Стандарты кодирования 5].

Блоки и область видимости

Ещё одной особенностью ECMAScript по отношению к другим C-подобным языкам является то, что в данном языке блоки не образуют области видимости (англ.). Объявленные в блоке переменные распространяются на всю функцию, содержащей блок[6][7].

В данном участке кода имеет место повторное объявление переменной в выделенных строках: <source lang="javascript" line number="1" highlight="3,7"> function foo() {

   var sum = 0;
   for (var i = 0; i < 42; i += 2) {
       var tmp = i + 2;
       sum += i * tmp;
   }
   for (var i = 1; i < 42; i += 2) {
       sum += i*i;
   }
   alert(tmp);
   return sum;

} foo(); </source> Кроме того, к переменной tmp, объявленной внутри первого из циклов (строка 5), в соответствии с синтаксисом языка вполне законно обратиться извне цикла (строка 10).

Из-за особенностей, связанных с областью видимости и блоками, в целях поддержания качества исходного кода рекомендуется объявлять переменные в начале функций[6][Стандарты кодирования 1][Стандарты кодирования 4].

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

Переменные определяются с помощью ключевого слова var. При объявлении переменная помещается в область видимости, соответствующую функции, в которой она объявляется. Если переменная объявляется вне функций, она помещается в глобальную область видимости. Создание переменной происходит при получении управления функцией с её объявлением. Или программой, если переменная глобальна. При создании переменной в ECMAScript она приобретает значение undefined. Если переменная объявлена с инициализацией, инициализация происходит не в момент создания переменной, а при выполнении строки с инструкцией var[Спецификация 9].

При раскомментировании выделенной строки на экран будет выводиться не number, а undefined: <source lang="javascript" highlight="4"> var a = 42; function foo() {

   alert(typeof a);
   // var a = 10;

} foo(); </source>

При создании переменной она приобретает внутреннее свойство {DontDelete} и её невозможно удалить с помощью оператора delete[Спецификация 9]. Исключение составляют переменные, объявленные в контексте eval[8][Спецификация 10].

Многие источники[9][10][11][12][13][14] декларируют возможность неявного объявления переменных в ECMAScript при осуществлении присваивания корректному идентификатору, не являющемуся формальным аргументом функции, без предварительного объявления с помощью var. Однако в терминологии спецификации языка в этом случае создаётся свойство глобального объекта, а не переменная[8][Спецификация 9].

Фиксация в стандарте оформления кода необходимости обязательного объявления переменных до их использования[Стандарты кодирования 1][Стандарты кодирования 4] (либо фиксация необходимости использовать пространства имён для всех глобальных объектов[Стандарты кодирования 2]) позволяет избегать трудноуловимых ошибок, предотвращая опасность взаимодействия одинаково названных переменных в разных участках кода[15].

Ключевые и зарезервированные слова

Следующие слова являются ключевыми в языке и не могут быть использованы как идентификаторы[Спецификация 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], и наличие большого количества ключевых и зарезервированных слов, большинство из которых не используется в языке, подвергалось критике[16].

Операторы

В ECMAScript имеются как операторы, использующие в качестве названий ключевые слова, так и операторы, использующие в качестве названий знаки препинания.

Классификация операторов

По убыванию приоритета операторы ECMAScript можно разбить в следующие группы:

  • . (доступ к свойству),[] (доступ к свойству),() (вызов функции), new (создание нового объекта),
  • ++ (инкремент), -- (декремент), - (унарный минус), + (унарный плюс), ~ (поразрядное дополнение), ! (логическое дополнение), delete (удаление свойства), typeof (определение примитивного типа данных), void (возврат неопределённого значения),
  • * (умножение), / (деление), % (остаток от деления),
  • + (сложение), - (вычитание), + (конкатенация строк),
  • << (сдвиг влево), >> (сдвиг вправо с расширением знакового разряда), >>> (сдвиг вправо с дополнением нулями),
  • < (меньше), <= (меньше или равно), > (больше), >= (больше или равно), instanceof (проверка типа объекта), in (проверка наличия свойства),
  • == (проверка на равенство), != (проверка на неравенство), === (проверка на идентичность), !== (проверка на неидентичность),
  • & (поразрядная конъюнкция),
  • ^ (поразрядное сложение по модулю 2),
  • | (поразрядная дизъюнкция),
  • && (конъюнкция),
  • || (дизъюнкция),
  • ?: (тернарная условная операция),
  • = (присваивание), *=, /=, +=, -=, <<=, >=, >>>=, &=, ^=, |= (присваивание с операцией),
  • , (множественное вычисление)[17].

Операторы ++, --, -, +, ~, !, delete, typeof, void, ?:, =, *=, /=, +=, -=, <<=, >=, >>>=, &=, ^=, |= правоассоциативны (то есть для них a op b op c эквивалентно a op b op c). Остальные операторы ECMAScript левоассоциативны[18].

По арности операторы ECMAScript делятся на следующие группы:

  • унарные (delete, void, typeof, ++, --, - (унарный минус), + (унарный плюс), ~, !, new)[Спецификация 15],
  • бинарные (., [], (), *, /, %, + (сложение), - (вычитание), + (конкатенация строк), <<, >>, >>>, <, <=, >, >=, instanceof, in, ==, !=, ===, !==, &, ^, |, &&, ||, =, *=, /=, +=, -=, <<=, >=, >>>=, &=, ^=, |=, ,),
  • тернарные (?:)[19],
  • операторы, не имеющие фиксированного количества операндов (())[20].

По положению знака операции относительно операндов операторы ECMAScript делятся на следующие группы:

  • префиксные (например, new, ++ (префиксный инкремент),
  • инфиксные (например, +, -),
  • постфиксные (например, ++ (постфиксный инкремент), -- (постфиксный декремент).

Также операторы классифицируются по типу операндов[21] и по характеру осуществляемого действия.

Особенности операторов ECMAScript

В ECMAScript нет оператора, позволяющего проверить, относится ли свойство непосредственно к объекту или является унаследованным. Такая проверка осуществляется с помощью метода hasOwnProperty(). В связи с тем, что данный метод не является оператором, он может быть переписан любым другим свойством[22].

Оператор + является единственным арифметическим оператором в языке, который перегружен для строковых аргументов. Если хотя бы один из операндов — строка, + действует как конкатенатор, в противном случае выполняется сложение[23][Спецификация 16].

В отличии от языков, где void является типом данных, в ECMAScript это оператор, возвращающий значение undefined[24].

Оператор == осуществляет проверку на равенство по алгоритму, состоящему из 10 шагов, подразумевающего в ряде случаев преобразование типов[Спецификация 17], что, в конечном счёте, может привести к неочевидным результатам[25].

Пример результатов работы == (во всех перечисленных случаях значением оператора с теми же аргументами будет false): <source lang="javascript"> alert("NaN" == NaN); // false alert(NaN != NaN); // true alert(true == 1); // true alert(true == 42); // false alert(null == 0); // false alert(0 == ""); // true alert("" == 0); // true alert("false" == false); // false alert(false == 0); // true alert(undefined == false); // false alert(null == false); // false alert(undefined == null); // true alert(" \t\r\n " == 0); // true </source>

Функции

Функции в ECMAScript являются объектами[26][27]. Конструктор, с помощью которого они создаются — Function(). Функции, как и любые другие объекты, могут храниться в переменных, объектах и массивах, могут передаваться как аргументы в другие функции и могут возвращаться функциями. Функции, как и любые другие объекты, могут иметь свойства. Существенной специфической чертой функций является то, что они могут быть вызваны[26].

Задание функций

В ECMAScript имеется два типа функций:

  • внутренние функции (например, parseInt),
  • функции, определённые в тексте программы.

Внутренние функции представляют собой встроенные объекты (см. ниже), не обязательно реализованные на ECMAScript[Спецификация 18].

В тексте программы именованную функцию в ECMAScript можно определить одним из следующих способов: <source lang="javascript"> // объявление функции function sum(arg1, arg2) {

   return arg1 + arg2;

}

// задание функции с помощью инструкции var sum2 = function(arg1, arg2) {

   return arg1 + arg2;

};

// задание функции с использованием объектной формы записи var sum3 = new Function("arg1", "arg2", "return arg1 + arg2;"); </source> Последний способ наименее предпочтителен, поскольку де-факто сводится к заданию функции с помощью выражения, но при этом порождает двойную интерпретацию кода (дополнительная интерпретация возникает при передаче кода в конструктор), что может негативно отразиться на производительности[27].

Первые два способа дают похожий, но не идентичный эффект. Усугубляет ситуацию то, что инструкция, использующаяся при задании функции может выглядеть очень похоже на объявление функции: во-первых, за ключевым словом function может следовать идентификатор[Спецификация 19], во-вторых, точка с запятой может быть опущена в силу механизма автодополнения строк точками с запятой[Спецификация 7]. Пример: <source lang="javascript"> // объявление функции function sum(arg1, arg2) {

   return arg1 + arg2;

}

// задание функции с помощью выражения var sum2 = function sum(arg1, arg2) {

   return arg1 + arg2;

}

function bar(){}; // использование объявления функции (function bar(){}) // использование соответствующей инструкции </source>

Наиболее существенной разницей между заданием функции с использовании объявления и заданием функции с помощью выражения является то, что объявления осуществляются до выполнения кода, а выражение по мере его выполнения[27]. Пример, иллюстрирующий разницу в порядке выполнения кода: <source lang="javascript"> alert(sum(3, 4)); // 7: объявление функции уже произошло к моменту выполнения этой строки function sum(arg1, arg2) {

   return arg1 + arg2;

}

alert(sum2(3, 4)); // ошибка[27]: sum2 ещё не задана var sum2 = function(arg1, arg2) {

   return arg1 + arg2;

}; </source>

Объявлением функций не следует пользоваться внутри условных конструкций[28], хотя в Gecko-браузерах это обработается интуитивным образом за счёт реализованного механизма функций как инструкций[29].

Присваивания функций

Поскольку функции в ECMAScript являются объектами, то есть относятся к ссылочному типу данных, идентификаторы функций являются переменными, хранящими ссылку на функцию. Проиллюстрировать это можно следующим кодом: <source lang="javascript" highlight="6"> var sum = function(arg1, arg2) {

   return arg1 + arg2;

};

alert(sum(3, 4)); // 7 var sum2 = sum; alert(sum2(4, 2)); // 6 sum = null; alert(sum2(42, 42)); // 84 </source> В выделенной строке следует обратить внимание на отсутствие оператора вызова функции (()) в правой части присваивания. Если бы в этой строке вместо sum было указано sum(), переменной sum2 присвоилась бы не функция, а результат её вызова. Ещё внимания заслуживает то, что после присваивания sum2 указывает не на копию функции, а на ту самую функцию, на которую указывает sum.

Перегрузка функций

В ECMAScript перегрузка функций не относится к свойствам языка, а её эффект обеспечивается за счёт использования других механизмов.

Пример, показывающий отсутствие перегрузки функций: <source lang="javascript"> function sum(arg1, arg2) {

   return arg1 + arg2;

}

function sum(arg1, arg2, arg3) {

   return arg1 + arg2 + arg3;

}

alert(sum(3, 4)); // NaN alert(sum(3, 4, 5)); // 12 </source>

Если объявлено несколько функций с одинаковыми названиями, более поздние объявления перезаписывают ранние объявления[27].

Тем не менее, эффект перегрузки функций достижим.

1. Проверка на undefined. Для того, чтобы проверить, передан ли в функцию фактический аргумент, можно осуществить проверку формального аргумента на идентичность значению undefined. Например: <source lang="javascript"> function sum(arg1, arg2, arg3) {

   if (arg3 !== undefined) {
       return arg1 + arg2 + arg3;
   } else {
       return arg1 + arg2;
   }

}

alert(sum(3, 4)); // 7 alert(sum(3, 4, 5)); // 12 </source>

2. Проверка типа. Кроме того, typeof, instanceof, constructor могут быть использованы для выяснения типа фактических аргументов и кастомизации поведения функции в зависимости от них.

<source lang="javascript"> function sum(arg1, arg2, arg3) {

   switch (typeof arg3) {
       case "undefined":
           return arg1 + arg2;
       case "number":
           return arg1 + arg2 + arg3;
       default:
           return arg1 + arg2 + " (" + arg3 + ")";
   }

}

alert(sum(3, 4)); // 7 alert(sum(3, 4, 5)); // 12 alert(sum(3, 4, "!")); // "12 (!)" </source>

3. Обращение к данным об аргументах. В функциях ECMAScript можно получить доступ к данным об аргументах с помощью объекта arguments[Спецификация 20]. Он, в частности, позволяет воспользоваться индексированием для доступа к конкретным переданным аргументам[27][30] и свойством length, хранящем количество фактически переданных аргументов, что может быть полезно при применении парадигмы обобщённого программирования.

<source lang="javascript"> function sum() {

   var res = 0;
   for (var i = 0; i < arguments.length; i++) {
       res += arguments[i];
   }
   return res;

}

alert(sum(3, 4)); // 7 alert(sum(3, 4, 5)); // 12 alert(sum(3, 4, 5, 7, 9)); // 28 </source>

Рекурсия

Функции ECMAScript допускают рекурсивный вызов. При задании функции с помощью инструкции без указания идентификатора после ключевого слова function внутри функции можно обратиться к ней с помощью свойства callee объекта arguments[Спецификация 20].

Пример рекурсивного вычисления факториала: <source lang="javascript"> var factorial = function(step, res) {

   res = res || 1; 
   if (step < 2) { 
       return res; 
   } 
   return arguments.callee(step - 1, step * res); 

};

alert(factorial(5)); // 120 </source>

На данный момент в ECMAScript не реализована хвостовая рекурсия, применяемая для оптимизации рекурсивных вызовов[31].

Функции обратного вызова

Основная статья: Callback (программирование)

В ECMAScript функция представляет собой объект первого класса и может быть передана в другую функцию как аргумент. Если она при этом вызывается в функции, в которую передаётся, то её называют функцией обратного вызова (или callback-функцией). Если при этом передаваемая функция не имеет имени, это анонимная функция обратного вызова (анонимная callback-функция)[32]. Основные причины использования функций обратного вызова:

  • избежание именования функции при оперировании с ней (способствует снижению числа глобальных переменных)[32],
  • делегирование вызова функции другой функции (способствует повышению выразительности кода)[32],
  • увеличение быстродействия[32],
  • упрощение оперирования с непродолжительными событиями[33].

Пример функции, возвращающей сумму от результатов выполнения переданной функции над аргументами: <source lang="javascript"> function sumOfResults(callback) {

   var result = 0;
   for (var i = 1; i < arguments.length; i++) {
       result += callback(arguments[i]);
   }
   return result;

}

var square = function(x) {

   return x * x;

}; alert(sumOfResults(square, 3, 4)); // 25 </source>

Замыкания

Функциям в ECMAScript присуща лексическая область видимости. Это означает, что область видимости определяется в момент определения функции (в отличии от динамической области видимости, при которой область видимости определяется в момент вызова функции)[34].

При объявлении функции последовательность областей видимости, относящихся к вложенным функциям сохраняется как составляющая состояния функции. То есть в процессе выполнения программы функции, обладающие доступом к локальным переменным объемлющих функций, сохраняют такой доступ на протяжении всего выполнения программы[34].

Механизм замыканий может использоваться для ограничения видимости переменных автономного участка программы с тем, чтобы не возникали конфликты имён при совместном с другим кодом использовании. Для этого код помещается в анонимную функцию, снабжаемую оператором вызова функции. <source lang="javascript"> (function() {

// Участок программы, доступ к переменным которого необходимо изолировать извне.

})(); </source> При этом определённые в участке программы функции становятся вложенными по отношению к добавленной анонимной функции и в них возможно осуществление доступа к локальным переменным анонимной функции (которые до её введения были глобальными). Однако извне анонимной функции доступ к ним осуществить нельзя: результат выполнения функции игнорируется.

Замыкания используются не только для запрещения доступа к ряду переменных, но и к модификации такого доступа. Это достигается с помощью функций, возвращающих другие функции. Пример функции-генератора последовательных чисел: <source lang="javascript"> var uniqueId = function() {

   var id = 0;
   return function() { return id++; };

}();

var aValue = uniqueId(); var anotherValue = uniqueId(); </source> За счёт использования замыкания доступ к переменной id имеет только функция, которая была присвоена переменной uniqueId.

Пример карринга: <source lang="javascript"> var multNumber = function(arg) {

   return function(mul) {
       return arg * mul;
   };

};

var multFive = multNumber(5); alert(multFive(7)); //35 </source>

Пример создания объекта, позволяющего осуществить доступ к свойству исключительно с помощью своих методов[35]: <source lang="javascript"> var myObject = function() {

   var value = 0; 
   return { 
       increment: function (inc) { 
           value += typeof inc === 'number' ? inc : 1; 
       }, 
       getValue: function (  ) { 
           return value; 
       } 
   } 

}();

alert(myObject.value === undefined); // true alert(myObject.getValue()); // 0 myObject.increment(9) myObject.increment(7) alert(myObject.getValue()); // 16 </source>

Пользуясь этим приёмом, можно использовать замыкание для эмуляции констант[36]. <source lang="javascript"> var getConstant = function() {

 var constants = {
   UPPER_BOUND: 100,
   LOWER_BOUND: -100
 };
 return function(constantName) {
   return constants[constantName];
 };

}();

alert(getConstant("LOWER_BOUND")); // -100 </source>

Регулярные выражения

Основная статья: Регулярные выражения

Синтаксис и функциональность регулярных выражений в ECMAScript сформировались под влиянием Perl 5[Спецификация 21] и допускают два вида синтаксиса: литеральный и объектный. <source lang="javascript"> var literalWay = /pattern/flags; var objectWay = new RegExp(pattern, flags); </source> В первом случае шаблон (pattern) и флаги (flags) указываются явно, не сопровождаясь дополнительными избыточными синтаксическими знаками: их разделителями служат слеши. Во втором случае шаблон и флаги должны представлять собой переменные, содержащие строковые значения, либо непосредственно строковые значения. Литеральная форма записи предпочтительнее тем, что не требует двойного[~ 2] экранирования метасимволов регулярных выражений, в отличии от объектной формы[37].

В качестве флагов в ECMAScript могут использоваться следующие символы:

Флаги регулярных выражений[37][Спецификация 21]
Флаг Описание
g глобальный режим: шаблон применяется ко всем соответствиям в строке, работа регулярного выражения не останавливается после первого найденного соответствия шаблону
i игнорирование регистра: при поиске соответствий регистр символов шаблона и строки игнорируются
m многострочный режим: строка, содержащая символы перевода строки, трактуется как несколько строк, разделённых символами перевода строки; работа регулярного выражения осуществляется во всех строках

Каждое регулярное выражение представляет собой объект со следующими свойствами:

Свойства объекта регулярное выражение в ECMAScript[37][Спецификация 21]
Свойство Тип Описание
global логический показывает, установлен ли флаг g
ignoreCase логический показывает, установлен ли флаг i
multiline логический показывает, установлен ли флаг m
lastIndex числовой соответствует номеру позиции в строке, в которой обнаружилось совпадение с шаблоном в результате предыдущего применения регулярного выражения или 0, если регулярное выражение ранее не применялось
source строковый строка, соответствующая шаблону регулярного выражения

Кроме того, для регулярных выражений определены следующие методы:

Методы объекта регулярное выражение в ECMAScript[37][Спецификация 21]
Метод Тип возвращаемого значения Описание
exec(handledString) объектный (массив) или null формирует массив подстрок, соответствующих заданному шаблону с учётом выставленных флагов. null, если никакая подстрока не соответствует шаблону
test(handledString) логический true, если нашлась строка, соответствующая шаблону и false в противном случае

Объекты

Реализация в языке

Объекты ECMAScript представляют собой неупорядоченные коллекции свойств, каждое из которых имеет один или более атрибутов, которые определяют как может быть использовано свойство — например, если в качестве значения атрибута ReadOnly установлена истина, то любая попытка выполняющегося ECMAScript-кода поменять значение этого свойства останется безрезультатной. Свойства представляют собой контейнеры, инкапсулирующие другие объекты, значения примитивных типов и методы[Спецификация 22].

Атрибуты свойств объектов ECMAScript[Спецификация 23]
Название Описание
ReadOnly Свойство является свойством только для чтения. Попытка поменять значение этого свойства, предпринятая в программе, останется безрезультатной. В некоторых случаях значение свойства с установленным атрибутом ReadOnly меняется в силу действий среды расширения языка, поэтому ReadOnly не следует понимать как неизменное
DontEnum Свойство не перечисляется циклом for-in
DontDelete Попытки удалить это свойство будут проигнорированы
Internal Свойство является внутренним. Оно не имеет названия и к нему нельзя получить доступ с помощью аксессоров. Доступ к этим свойствам определяется реализацией языка.

Объекты ECMAScript подразделяются на базовые (native) и объекты расширения (host). Под базовыми понимаются любые объекты, независимые от окружения, относящегося к расширению языка. Некоторые из базовых объектов являются встроенными (built-in): существующими с самого начала выполнения программы. Другие могут быть созданы, когда программа выполняется. Объекты расширения предоставляются расширением ECMAScript, а для ECMAScript это значит, что они входят в объектную модель документа или в объектную модель браузера[Спецификация 2].

Синтаксис

Для задания объектов может использоваться объектная и литеральная формы. Объектная форма задания объекта имеет синтаксис, аналогичный Java, но, в отличии от него, скобки в ECMAScript требуется использовать только при передаче аргументов в конструктор[38]. Синтаксически следующие записи эквивалентны: <source lang="javascript"> var obj1 = new Object(); var obj2 = new Object; var obj3 = {}; </source> Однако второй вариант использовать не рекомендуется[38]. Дуглас Крокфорд рекомендует избегать и первого варианта, отдавая предпочтение литеральной форме, которую он считает большим достоинством языка[39].

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

Каждый объект в языке имеет следующие свойства:

Свойства объектов ECMAScript[38]
Название Краткое описание
constructor Функция, использованная для создания объекта (в примерах выше это Object())
hasOwnProperty(propertyName) Показывает, существует ли данное свойство в объекте (не в его прототипе)
isPrototypeOf(object) Определяет, находится ли объект в цепи прототипов объекта-аргумента
propertyIsEnumerable(propertyName) Показывает, является ли свойство с данным названием перечислимым в цикле for-in
toString() Возвращает представление объекта в виде строки
valueOf() Возвращает значение this. Если же объект является результатом вызова конструктора объекта расширения, значение valueOf() зависит от реализации[Спецификация 2]. Зачастую в качестве возвращаемого значения выступает значение примитивного типа, соответствующее объекту. Как правило, результат данного метода совпадает с результатом toString(). Объекты, созданные с помощью конструктора Date() — яркий пример, где результаты toString() и valueOf() не совпадает[38].

Доступ к свойствам объекта осуществляется использованием точечной и скобочной записи: <source lang="javascript"> var obj = new Object(); alert(obj.constructor === obj["constructor"]); // true — использование точечной и скобочной записи для доступа к свойству

var foo = obj["toString"]; // использование скобочной записи для сохранения функции в переменную var result = obj["toString"](); // сохранение результата вызова функции в переменную alert(foo()); // вывод на экран результата вызова сохранённой функции alert(result);

var boo = obj.toString; // аналогично с использованием точечной записи var res = obj.toString(); alert(boo()); alert(res); </source>

Задание новых свойств может осуществляться динамически. <source lang="javascript"> var country = new Object(); country["name"] = "Russia"; // использование скобочной записи country.foundationYear = 862; // использование точечной записи

var country2 = {

   "name":           "Russia",
   "foundationYear": 862

}; // использование литеральной формы </source>

Подходы к созданию объектов

Создание объектов описанным в предыдущем разделе способом может быть непрактичным из-за необходимости дублировать код[40]. Если в программе происходит манипуляция с большим количеством однотипных объектов, разработчик имеет возможность выбрать одну из используемых в языке техник[40]:

фабрика объектов
функция, создающая объект и возвращающая его в качестве своего значения,
конструктор
функция, использующая ключевое слово this для формирования свойств объекта, создаваемого ей с помощью оператора new,
прототипный подход
задействование свойства prototype функции для вынесения общих свойств объектов,
смешанный подход конструктор-прототип
использование конструктора для задания свойств объектов, не являющихся методами и прототипного подхода — для задания методов,
метод динамического прототипа
заключение кода, относящегося к функции создания объектов на основе смешанного подхода конструктор-прототип, в неё одну с обеспечением однократности присваивания свойств прототипа,
метод паразитического конструктора
использование new с функцией фабрики объектов.

В языке нет классов, однако их можно эмулировать за счёт использования конструкторов. Пример эмуляции класса в ECMAScript:

<source lang="javascript"> function MyClass() {

   this.myValue1 = 1;
   this.myValue2 = 2;

}

MyClass.prototype.myMethod = function() {

   return this.myValue1 * this.myValue2;

}

var mc = new MyClass(); mc.myValue1 = mc.myValue2 * 2; var i = mc.myMethod(); </source>

Особенности наследования в ECMAScript

Для каждой из составляющих объекта можно рассматривать наследование. При наследовании интерфейса родителя без того, чтобы потомок использовал функциональность предка, говорят о наследовании интерфейса. При наследовании состояния осуществляется наследование объектом-потомком структуры данных объекта-предка. При наследовании функциональности речь идёт о наследовании вместе с интерфейсом и кода методов. Как правило это влечёт необходимость организации наследования состояния, что делает разумным объединение наследования состояния и наследования функциональности в наследование реализации[41].

В отношении ECMAScript неприменимо лишь наследование интерфейсов, поскольку функции в языке не имеют сигнатур[40].

О возможностях, предоставляемых языком для организации наследования можно судить, например, по приводимому[42] Стояном Стефановым списку из двенадцати разных способов организации наследования.

Стандарты ECMAScript

Ссылки

Примечания

  1. ↑ Zakas N. ECMAScript // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 3 — 7. — ISBN 978-0-470-22780-0
  2. ↑ 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
  3. ↑ 3,0 3,1 Дэвид Флэнаган. 3. Типы данных и значения // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 39 — 66. — ISBN 5-93286-103-7
  4. ↑ 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. — Т. 5673. — С. 238 – 255. — ISBN 978-3-642-03236-3.
  5. ↑ Crockford D. A.3. Semicolon Insertion // JavaScript: The Good Parts. — 2008. — P. 102. — ISBN 978-0-596-51774-8
  6. ↑ 6,0 6,1 Crockford D. A.2. Scope // JavaScript: The Good Parts. — 2008. — P. 36. — ISBN 978-0-596-51774-8
  7. ↑ Дэвид Флэнаган. 4.3.1. Отсутствие блочной области видимости // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 70 — 71. — ISBN 5-93286-103-7
  8. ↑ 8,0 8,1 Сошников, Дмитрий Тонкости ECMA-262-3. Часть 2. Объект переменных. (2009-06-27). Проверено 6 ноября 2009.
  9. ↑ Дэвид Флэнаган. 4.2. Объявление переменных // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 68. — ISBN 5-93286-103-7
  10. ↑ Koch Peter-Paul Implicit variable declaration // ppk on JavaScript / Editor: Wendy Sharp. — 1st ed. — New Riders Press, 2006. — 528 p. — ISBN 978-0-321-42330-6
  11. ↑ Zakas N. Variables // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 26, 27. — ISBN 978-0-470-22780-0
  12. ↑ Souders S. Use Local Variables // Even Faster Web Sites: Performance Best Practices for Web Developers. — 1st ed. — USA: O'Reilly Media, 2009. — P. 81 — 83. — ISBN 0596522304
  13. ↑ Easttom C. Variable Declaration // Advanced Javascript. — 3rd ed. — USA: Wordware Publishing, Inc., 2008. — 81 — 83 p. — ISBN 1-59822-033-0
  14. ↑ 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
  15. ↑ 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
  16. ↑ Crockford D. A.4. Reserved Words // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  17. ↑ Дэвид Флэнаган. 5.2. Обзор операторов // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 78 — 79. — ISBN 5-93286-103-7
  18. ↑ Дэвид Флэнаган. 5.2.4 Ассоциативность операторов // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 81. — ISBN 5-93286-103-7
  19. ↑ Дэвид Флэнаган. 5.2.1 Количество операндов // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 79. — ISBN 5-93286-103-7
  20. ↑ Дэвид Флэнаган. 5.10.8 Оператор вызова функции // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 98. — ISBN 5-93286-103-7
  21. ↑ Дэвид Флэнаган. 5.2.2 Тип операндов // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 80. — ISBN 5-93286-103-7
  22. ↑ Crockford D. A.13. hasOwnProperty // JavaScript: The Good Parts. — 2008. — P. 107. — ISBN 978-0-596-51774-8
  23. ↑ Crockford D. A.8. + // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  24. ↑ Crockford D. B.12. void // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  25. ↑ Crockford D. B.1. == // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  26. ↑ 26,0 26,1 Crockford D. 4.1. Function Objects // JavaScript: The Good Parts. — 2008. — P. 26. — ISBN 978-0-596-51774-8
  27. ↑ 27,0 27,1 27,2 27,3 27,4 27,5 Zakas N. The Function Type // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 122 — 130. — ISBN 978-0-470-22780-0
  28. ↑ Juriy "kangax" Zaytsev. Named function expressions demystified (англ.). — Статья, детально описывающая разницу между заданием функции с помощью объявления и заданием функции с помощью выражения. Проверено 19 октября 2009.
  29. ↑ Maian и др. Conditionally defining a function (англ.). Functions and function scope. — Описание деталей реализации функций как выражений в контексте объявлений внутри условий. Проверено 19 октября 2009.
  30. ↑ Crockford D. 4.4. Arguments // JavaScript: The Good Parts. — 2008. — P. 31. — ISBN 978-0-596-51774-8
  31. ↑ Crockford D. 4.8. Recursion // JavaScript: The Good Parts. — 2008. — P. 35. — ISBN 978-0-596-51774-8
  32. ↑ 32,0 32,1 32,2 32,3 Stefanov 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
  33. ↑ Crockford D. 4.11. Callbacks // JavaScript: The Good Parts. — 2008. — P. 40. — ISBN 978-0-596-51774-8
  34. ↑ 34,0 34,1 Дэвид Флэнаган. 8.8. Область видимости функций и замыкания // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 156 — 163. — ISBN 5-93286-103-7
  35. ↑ Crockford D. 4.10. Closure // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  36. ↑ Harmes R., Diaz D. Constants // Pro JavaScript™ Design Patterns. — USA: Apress, 2008. — P. 37, 38. — ISBN 1-59059-908-X
  37. ↑ 37,0 37,1 37,2 37,3 Zakas N. The RegExp Type // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 115 — 122. — ISBN 978-0-470-22780-0
  38. ↑ 38,0 38,1 38,2 38,3 Zakas N. The Object Type // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 40 — 41. — ISBN 978-0-470-22780-0
  39. ↑ Crockford D. JSON // JavaScript: The Good Parts. — 2008. — P. 136. — ISBN 978-0-596-51774-8
  40. ↑ 40,0 40,1 40,2 Zakas N. 6. Object-Oriented Programming // Professional JavaScript for Web Developers. — 2nd ed. — USA, Canada: Wiley Publishing, Inc., 2009. — P. 151 — 182. — ISBN 978-0-470-22780-0
  41. ↑ Кузнецов, Михаил Наследование реализации в распределённых объектных системах. Издательство «Открытые системы» (11 декабря 2002). Проверено 1 ноября 2009.
  42. ↑ Stefanov S. Chapter 6. Inheritance. Summary // Object-Oriented JavaScript: Create scalable, reusable high-quality JavaScript applications and libraries. — 1st ed.. — Packt Publishing, 2008. — P. 194 — 198. — ISBN 184719414

Спецификации ECMAScript

  1. ↑ TC39. Brief History // ECMAScript Language Specification. — 5th ed. — 2009.
  2. ↑ 2,0 2,1 2,2 2,3 TC39. 4.3. Definitions // ECMAScript Language Specification. — 5th ed. — 2009. — P. 4. Ошибка цитирования Неверный тег <ref>: название «specDefinitions» определено несколько раз для различного содержимого
  3. ↑ TC39. 8.5. The Number Type // ECMAScript Language Specification. — 5th ed. — 2009. — P. 29.
  4. ↑ 4,0 4,1 4,2 4,3 TC39. 8. Types // ECMAScript Language Specification. — 3rd ed. — 1999. — P. 24.
  5. ↑ 5,0 5,1 5,2 5,3 TC39. 8. Types // 3rd edition, December 1999.pdf ECMAScript Language Specification. — 5th ed. — 2009. — P. 28.
  6. ↑ TC39. 12. Statements // ECMAScript Language Specification. — 5th ed. — 2009. — P. 86 — 97.
  7. ↑ 7,0 7,1 7,2 7,3 TC39. 7.9. Automatic Semicolon Insertion // ECMAScript Language Specification. — 5th ed. — 2009. — P. 25 — 28.
  8. ↑ TC39. 12. Statements // ECMAScript Language Specification. — 3rd ed. — 1999. — P. 61 — 71.
  9. ↑ 9,0 9,1 9,2 TC39. 12.2. Variable Statement // ECMAScript Language Specification. — 5th ed. — 2009. — P. 87, 88.
  10. ↑ TC39. 10.2.2. Eval Code // 3rd edition, December 1999.pdf ECMAScript Language Specification. — 3rd ed. — 1999. — P. 39.
  11. ↑ TC39. 7.6.1.1. Keywords // ECMAScript Language Specification. — 5th ed. — 2009. — P. 18.
  12. ↑ TC39. 7.5.2. Keywords // 3rd edition, December 1999.pdf ECMAScript Language Specification. — 3rd ed. — 1999. — P. 13 — 14.
  13. ↑ 13,0 13,1 TC39. 7.6.1. Reserved Words // ECMAScript Language Specification. — 5th ed. — 2009. — P. 18, 19.
  14. ↑ TC39. 7.5.3. Future Reserved Words // 3rd edition, December 1999.pdf ECMAScript Language Specification. — 3rd ed. — 1999. — P. 15.
  15. ↑ TC39. 11.4. Unary Operators // ECMAScript Language Specification. — 5th ed. — 2009. — P. 70 — 72.
  16. ↑ TC39. 11.6.1 The Addition operator ( + ) // ECMAScript Language Specification. — 5th ed. — 2009. — P. 74, 75.
  17. ↑ TC39. 11.9.3. The Abstract Equality Comparison Algorithm // ECMAScript Language Specification. — 5th ed. — 2009. — P. 80, 81.
  18. ↑ TC39. 4.3. Definitions // ECMAScript Language Specification. — 5th ed. — 2009. — P. 4 — 7.
  19. ↑ TC39. 13 Function Definition // ECMAScript Language Specification. — 5th ed. — 2009. — P. 97, 98.
  20. ↑ 20,0 20,1 TC39. 10.6. Arguments Object // ECMAScript Language Specification. — 5th ed. — 2009. — P. 60 — 62.
  21. ↑ 21,0 21,1 21,2 21,3 TC39. 15.10. RegExp (Regular Expression) Objects // ECMAScript Language Specification. — 5th ed. — 2009. — P. 179 — 196.
  22. ↑ TC39. 4.2. Language Overview // ECMAScript Language Specification. — 5th ed. — 2009. — P. 2 — 4.
  23. ↑ TC39. 8.6.1. Property attributes // ECMAScript Language Specification. — 3rd ed. — 1999. — P. 25, 26.

Комментарии

  1. ↑ Только в отношении do-while
  2. ↑ Одним обратным слешем экранируются метасимволы строк (например, \t). Для экранирования метасимволов регулярных выражений используется двойной обратный слеш (например, \\s)

Стандарты оформления кода JavaScript

  1. ↑ 1,0 1,1 1,2 Crockford, Douglas Code Conventions for the JavaScript Programming Language (англ.). Douglas Crockford's JavaScript. — Стандарт оформления кода JavaScript Дугласа Крокфорда. Проверено 5 октября 2009.
  2. ↑ 2,0 2,1 JavaScript Code Conventions (англ.). Echo Web Framework. NextApp, Inc. — Стандарт оформления кода JavaScript, принятый для Echo Web Framework. Проверено 5 октября 2009.
  3. ↑ Amaram, Rahul Javascript Naming Conventions, Coding Guidelines and Best Practices (англ.). Echo Web Framework. — Стандарт оформления кода JavaScript Рауля Амарама. Проверено 5 октября 2009.
  4. ↑ 4,0 4,1 4,2 Komenda, Klaus JavaScript Coding Guidelines and Standards (англ.). Сайт австрийского веб-разработчика Клауса Коменда. — Стандарт оформления кода JavaScript Клауса Коменда. Проверено 5 октября 2009.
  5. ↑ JavaScript coding style (англ.). GNOME. — Стандарт оформления кода JavaScript в GNOME. Проверено 24 декабря 2009.

ca:ECMAScript da:ECMAScript en:ECMAScript es:ECMAScript fr:ECMAScript hu:ECMAScript ja:ECMAScript ko:ECMA스크립트 no:ECMAScript pl:ECMAScript pt:ECMAScript sv:Ecmascript th:ECMAScript uk:ECMAScript zh:ECMAScript

Если вам нравится SbUP.com Сайт, вы можете поддержать его - BTC: bc1qppjcl3c2cyjazy6lepmrv3fh6ke9mxs7zpfky0 , TRC20 и ещё....

→