ECMAScript это:

ECMAScript
ECMAScript
Класс языка:

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

Появился в:

1995

Автор(ы):

Брендан Айх

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

утиная

Диалекты:

JavaScript, JScript, ActionScript, JScript .NET, QtScript

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

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]

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

Пример изменения смысла инструкции

return{ 
    status: "complete"
};

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

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

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

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

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

В данном участке кода имеет место повторное объявление переменной в выделенных строках:

  1. function foo() {
    
  2.     var sum = 0;
    
  3.     for (var i = 0; i < 42; i += 2) {
    
  4.         var tmp = i + 2;
    
  5.         sum += i * tmp;
    
  6.     }
    
  7.     for (var i = 1; i < 42; i += 2) {
    
  8.         sum += i*i;
    
  9.     }
    
  10.     alert(tmp);
    
  11.     return sum;
    
  12. }
    
  13. foo();
    

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

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

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

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

При раскомментировании выделенной строки на экран будет выводиться не number, а undefined:

var a = 42;
function foo() {
    alert(typeof a);
    // var a = 10;}
foo();

При создании переменной она приобретает внутреннее свойство {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):

alert("NaN" == NaN);       // false
alert(NaN == NaN);         // false
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

Функции

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

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

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

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

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

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

// объявление функции
function sum(arg1, arg2) {
    return arg1 + arg2;
}
 
// задание функции с помощью инструкции
var sum2 = function(arg1, arg2) {
    return arg1 + arg2;
};
 
// задание функции с использованием объектной формы записи
var sum3 = new Function("arg1", "arg2", "return arg1 + arg2;");

Последний способ наименее предпочтителен, поскольку де-факто сводится к заданию функции с помощью выражения, но при этом порождает двойную интерпретацию кода (дополнительная интерпретация возникает при передаче кода в конструктор), что может негативно отразиться на производительности[27].

Первые два способа дают похожий, но не идентичный эффект. Усугубляет ситуацию то, что инструкция, использующаяся при задании функции может выглядеть очень похоже на объявление функции: во-первых, за ключевым словом function может следовать идентификатор[Спецификация 19], во-вторых, точка с запятой может быть опущена в силу механизма автодополнения строк точками с запятой[Спецификация 7]. Пример:

// объявление функции
function sum(arg1, arg2) {
    return arg1 + arg2;
}
 
// задание функции с помощью выражения
var sum2 = function sum(arg1, arg2) {
    return arg1 + arg2;
}
 
function bar(){};  // использование объявления функции
(function bar(){}) // использование соответствующей инструкции

Наиболее существенной разницей между заданием функции с использованием объявления и заданием функции с помощью выражения является то, что в первом случае создание переменной и присваивание ей в качестве значения функции осуществляются до выполнения кода при входе в контекст исполнения. Во втором случае переменная получает значение инциализатора при выполнении оператора присваивания. При создании же переменной, осуществляемом при входе в контекст исполнения, она инициализируется значением undefined[Спецификация 20][28] (подробнее см. в разделе Объявление переменных).

Пример, иллюстрирующий разницу в порядке выполнения кода:

alert(sum(3, 4)); // 7: переменная sum к моменту выполнения этой строки уже создана и в качестве значения ей присвоена функция
function sum(arg1, arg2) {
    return arg1 + arg2;
}
 
alert(sum2(3, 4)); // ошибка: переменная sum2 к моменту выполнения этой строки уже создана, но в качестве значения ей присвоено undefined
var sum2 = function(arg1, arg2) {
    return arg1 + arg2;
};

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

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

Поскольку функции в ECMAScript являются объектами, то есть относятся к ссылочному типу данных, идентификаторы функций являются переменными, хранящими ссылку на функцию. Проиллюстрировать это можно следующим кодом:

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

В выделенной строке следует обратить внимание на отсутствие оператора вызова функции (()) в правой части присваивания. Если бы в этой строке вместо sum было указано sum(), переменной sum2 присвоилась бы не функция, а результат её вызова. Ещё внимания заслуживает то, что после присваивания sum2 указывает не на копию функции, а на ту самую функцию, на которую указывает sum.

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

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

Пример, показывающий отсутствие перегрузки функций:

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

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

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

1. Проверка на undefined. Для того, чтобы проверить, передан ли в функцию фактический аргумент, можно осуществить проверку формального аргумента на идентичность значению undefined. Например:

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

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

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, "!"));  // "7 (!)"

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

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

Рекурсия

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

Пример рекурсивного вычисления факториала:

var factorial = function(step, res) {
    res = res || 1; 
    if (step < 2) { 
        return res; 
    } 
    return arguments.callee(step - 1, step * res); 
}; 
 
alert(factorial(5));           // 120

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

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

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

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

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

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

Замыкания

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

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

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

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

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

Замыкания используются не только для запрещения доступа к ряду переменных, но и к модификации такого доступа. Это достигается с помощью функций, возвращающих другие функции. Пример функции-генератора последовательных чисел:

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

За счёт использования замыкания доступ к переменной id имеет только функция, которая была присвоена переменной uniqueId.

Пример карринга:

var multNumber = function(arg) {
    return function(mul) {
        return arg * mul;
    };
};
 
var multFive = multNumber(5);
alert(multFive(7)); //35

Пример создания объекта, позволяющего осуществить доступ к свойству исключительно с помощью своих методов[36]:

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

Пользуясь этим приёмом, можно использовать замыкание для эмуляции констант[37].

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

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

Синтаксис и функциональность регулярных выражений в ECMAScript сформировались под влиянием Perl 5[Спецификация 22] и допускают два вида синтаксиса: литеральный и объектный.

var literalWay = /pattern/flags;
var objectWay  = new RegExp(pattern, flags);

В первом случае шаблон (pattern) и флаги (flags) указываются явно, не сопровождаясь дополнительными избыточными синтаксическими знаками: их разделителями служат слеши. Во втором случае шаблон и флаги должны представлять собой переменные, содержащие строковые значения, либо непосредственно строковые значения. Литеральная форма записи предпочтительнее тем, что не требует двойного[~ 2] экранирования метасимволов регулярных выражений, в отличие от объектной формы[38].

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

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

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

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

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

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

Объекты

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

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

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

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

Синтаксис

Для задания объектов может использоваться объектная и литеральная формы. Объектная форма задания объекта имеет синтаксис, аналогичный Java, но, в отличие от него, скобки в ECMAScript требуется использовать только при передаче аргументов в конструктор[39]. Синтаксически следующие записи эквивалентны:

var obj1 = new Object();
var obj2 = new Object;
var obj3 = {};

Однако второй вариант использовать не рекомендуется[39]. Дуглас Крокфорд рекомендует избегать и первого варианта, отдавая предпочтение литеральной форме, которую он считает большим достоинством языка[40].

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

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

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

Доступ к свойствам объекта осуществляется использованием точечной и скобочной записи:

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);

Задание новых свойств может осуществляться динамически.

var country            = new Object();
country["name"]       = "Russia"; // использование скобочной записи
country.foundationYear = 862; // использование точечной записи
 
var country2 = {
    "name":           "Russia",
    "foundationYear": 862
}; // использование литеральной формы

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

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

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

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

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();

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

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

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

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

Стандарты 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. 1 2 Дэвид Флэнаган. 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. 1 2 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. 1 2 Сошников, Дмитрий Тонкости ECMA-262-3. Часть 2. Объект переменных. (27 июня 2009). Архивировано из первоисточника 18 февраля 2012. Проверено 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. 1 2 Crockford D. 4.1. Function Objects // JavaScript: The Good Parts. — 2008. — P. 26. — ISBN 978-0-596-51774-8
  27. 1 2 3 4 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. Сошников, Дмитрий Тонкости ECMA-262-3. Часть 1. Контексты исполнения. (26 июня 2009). Проверено 12 октября 2010.
  29. Juriy "kangax" Zaytsev. Named function expressions demystified  (англ.). — Статья, детально описывающая разницу между заданием функции с помощью объявления и заданием функции с помощью выражения.(недоступная ссылка — история) Проверено 19 октября 2009.
  30. Maian и др. Conditionally defining a function  (англ.). Functions and function scope. — Описание деталей реализации функций как выражений в контексте объявлений внутри условий. Проверено 19 октября 2009.
  31. Crockford D. 4.4. Arguments // JavaScript: The Good Parts. — 2008. — P. 31. — ISBN 978-0-596-51774-8
  32. Crockford D. 4.8. Recursion // JavaScript: The Good Parts. — 2008. — P. 35. — ISBN 978-0-596-51774-8
  33. 1 2 3 4 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
  34. Crockford D. 4.11. Callbacks // JavaScript: The Good Parts. — 2008. — P. 40. — ISBN 978-0-596-51774-8
  35. 1 2 Дэвид Флэнаган. 8.8. Область видимости функций и замыкания // JavaScript. Подробное руководство = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб.: «Символ-Плюс», 2008. — С. 156 — 163. — ISBN 5-93286-103-7
  36. Crockford D. 4.10. Closure // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8
  37. Harmes R., Diaz D. Constants // Pro JavaScript™ Design Patterns. — USA: Apress, 2008. — P. 37, 38. — ISBN 1-59059-908-X
  38. 1 2 3 4 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
  39. 1 2 3 4 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
  40. Crockford D. JSON // JavaScript: The Good Parts. — 2008. — P. 136. — ISBN 978-0-596-51774-8
  41. 1 2 3 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
  42. Кузнецов, Михаил Наследование реализации в распределённых объектных системах. Издательство «Открытые системы» (11 декабря 2002). Архивировано из первоисточника 18 февраля 2012. Проверено 1 ноября 2009.
  43. 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. 1 2 3 4 TC39. 4.3. Definitions // ECMAScript Language Specification. — 5th ed. — 2009. — P. 4.
  3. TC39. 8.5. The Number Type // ECMAScript Language Specification. — 5th ed. — 2009. — P. 29.
  4. 1 2 3 4 TC39. 8. Types // ECMAScript Language Specification. — 3rd ed. — 1999. — P. 24.
  5. 1 2 3 4 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. 1 2 3 4 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. 1 2 3 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. 1 2 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. TC39. 12.2 Variable Statement // ECMAScript Language Specification. — 5th ed. — 2009. — P. 87, 88.
  21. 1 2 TC39. 10.6. Arguments Object // ECMAScript Language Specification. — 5th ed. — 2009. — P. 60 — 62.
  22. 1 2 3 4 TC39. 15.10. RegExp (Regular Expression) Objects // ECMAScript Language Specification. — 5th ed. — 2009. — P. 179 — 196.
  23. TC39. 4.2. Language Overview // ECMAScript Language Specification. — 5th ed. — 2009. — P. 2 — 4.
  24. TC39. 8.6.1. Property attributes // ECMAScript Language Specification. — 3rd ed. — 1999. — P. 25, 26.

Комментарии

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

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

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

Wikimedia Foundation. 2010.

Смотреть что такое "ECMAScript" в других словарях:

  • Ecmascript — est un langage de programmation de type script standardisé par Ecma International dans le cadre de la spécification ECMA 262. Il s agit donc d un standard dont les spécifications sont implémentées dans la plupart des langages script, comme… …   Wikipédia en Français

  • ECMAScript — est un langage de programmation de type script standardisé par Ecma International dans le cadre de la spécification ECMA 262. Il s agit donc d un standard dont les spécifications sont mises en œuvre dans différents langages script, comme… …   Wikipédia en Français

  • ECMAScript — Saltar a navegación, búsqueda ECMAScript es una especificación de lenguaje de programación publicada por ECMA International. El desarrollo empezó en 1996 y estuvo basado en el popular lenguaje JavaScript propuesto como estándar por Netscape… …   Wikipedia Español

  • ECMAScript — es una especificación de lenguaje de programación publicada por ECMA International. El desarrollo empezó en 1996 y estuvo basado en el popular lenguaje JavaScript propuesto como estándar por Netscape corporation. Actualmente está aceptado como el …   Enciclopedia Universal

  • ECMAScript — „ECMAScript“ kalba statusas T sritis informatika apibrėžtis ↑Scenarijų kalba, standartizuota Europos informacinių ir komunikacinių sistemų standartų asociacijos (ECMA International) ECMA 262 specifikacija. Ši kalba atsirado kaip scenarijų kalbos… …   Enciklopedinis kompiuterijos žodynas

  • ECMAScript — ECMAScript,   eine Scriptsprache für HTML Dokumente, die dem von der ECMA herausgegebenen Standard ECMA 262 (dritte Ausgabe Dezember 1999) entspricht. Der Standard enthält die wesentlichen Elemente von Netscapes JavaScript sowie einige Punkte aus …   Universal-Lexikon

  • ECMAScript — Infobox programming language name = ECMAScript paradigm = Multi paradigm: prototype oriented, functional, imperative, scripting year = 1997 designer = Brendan Eich, Ecma International turing complete = Yes typing = duck, weak, dynamic… …   Wikipedia

  • ECMAScript — JavaScript ist eine Skriptsprache, die hauptsächlich für das DOM Scripting in Web Browsern eingesetzt wird. Dabei ist unter JavaScript die Gesamtheit aus den Eigenschaften des Browsers (beziehungsweise Clients oder Scripting Hosts) sowie des… …   Deutsch Wikipedia

  • ECMAscript — …   Википедия

  • EcmaScript — …   Википедия

Книги

Другие книги по запросу «ECMAScript» >>


Поделиться ссылкой на выделенное

Прямая ссылка:
Нажмите правой клавишей мыши и выберите «Копировать ссылку»