Interested Article - ECMAScript
- 2021-06-27
- 1
ECMAScript — это встраиваемый расширяемый не имеющий средств ввода-вывода язык программирования , используемый в качестве основы для построения других скриптовых языков .
ECMAScript стандартизирован международной организацией ECMA в спецификации ECMA-262 . Расширения языка: JavaScript , JScript и ActionScript .
История
Язык возник на основе нескольких технологий, самыми известными из которых являются языки JavaScript и JScript . Разработка первой редакции спецификации началась в ноябре 1996 года. Принятие спецификации состоялось в июне 1997 года. Будучи отправленной в ISO/IEC JTC 1 для принятия по процедуре Fast-Tracking , она послужила основой международного стандарта . В июне 1998 года общим собранием ECMA была принята вторая редакция ECMA-262, соответствующая ISO/IEC 16262. Третья редакция спецификации отличалась от предыдущей введением поддержки регулярных выражений, улучшением поддержки строк, введением новых управляющих конструкций, механизма исключений, форматирования при численном вводе и некоторыми другими изменениями .
Семантика и синтаксис
Типы данных
В ECMAScript поддерживаются пять примитивных типов данных :
- ( англ. Number ),
- строковый ( англ. String ),
- логический ( англ. Boolean ),
- ( англ. Null ),
- ( англ. Undefined ) .
Числовой тип данных в ECMAScript соответствует 64-битному формату чисел с плавающей запятой, определённому стандартом IEEE 754-2008 за исключением того, что различные значения Not-a-Number , определяемые в стандарте , представляются в данном языке единственным специальным значением NaN .
Нулевой и неопределённый типы данных неформально причисляются к «тривиальным» типам, поскольку каждый из них определяет только одно значение .
Также в языке имеется «составной» тип данных :
- ( англ. Object ).
Помимо перечисленных шести типов данных, в ECMAScript имеется поддержка ещё семи, используемых исключительно для хранения промежуточных результатов вычисляемых выражений:
- ссылочный ( англ. Reference ),
- ( англ. List ),
- ( англ. Completion ).
- (новый ) описатель свойства ( англ. Property Descriptor ),
- (новый ) идентификатор свойства ( англ. Property Identifier ),
- (новое ) лексическое окружение ( англ. Lexical Environment ),
- (новая ) запись окружения ( англ. Environment Record ).
Популярность языка JavaScript и нетривиальность обработки данных, относящихся к разным типам, обусловили развёртывание академических исследований в области анализа типов данных ECMAScript, ставящих своей целью создание полноценного анализатора кода, который можно было бы применять в интегрированных средах разработки .
Инструкции
В ECMAScript имеется пятнадцать различных видов инструкций, данные о которых представлены в таблице ниже:
Название | Оригинальное название | Краткие сведения | Завершающая ; |
---|---|---|---|
Блок | англ. Block | {[<инструкции>]} | − |
Объявление переменной | англ. VariableStatement | var <список объявления переменных> | + |
Пустая инструкция | англ. EmptyStatement | ; | + |
Выражение | англ. ExpressionStatement | [строка до ∉ {{, function}] инструкция | + |
Условие | англ. IfStatement |
if (<инструкция>) <выражение>[ else <выражение>]
|
− |
Цикл | англ. IterationStatement |
do <выражение> while (<инструкция>)
while (<инструкция>) <выражение>
|
+/− |
Продолжение | англ. 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 <блок> |
− |
(новое ) Отладчик | англ. Debugger | debugger | − |
Автодополнение строк точками с запятой
Несмотря на обязательность точки с запятой в случаях, отмеченных в четвёртой колонке, спецификация декларирует механизм автодополнения строк точками с запятой , приводящий к тому, что при наличии переноса строки инструкция до переноса может быть снабжена этим знаком , что является объектом критики .
Инструкции, меняющие смысл при использовании перевода строки внутри
- Унарный постфиксный ++
- Унарный постфиксный --
- Продолжение
- Прерывание
- Возврат
- Генерация исключения
Пример изменения смысла инструкции
return
{
status: "complete"
};
Здесь выделенная строка содержит допустимую языком инструкцию и, поскольку далее следует перевод строки, срабатывает механизм автодополнения строк точками с запятой. Вместо того, чтобы функция, содержащая приведённый код, в качестве своего значения вернула объект со свойством
status
, она вернёт
undefined
.
Несмотря на то, что литеральная форма записи объекта блоком кода не является, единообразие в расстановке скобок может приводить к ошибкам. Снизить вероятность их появления способна выработка или принятие подходящего стандарта оформления кода . Играет роль выбор стиля отступов . В частности, стили Олмана и Уайтсмита , а также и стиль GNU для кода JavaScript не рекомендуются к использованию большинством руководств в отличие от стилей K&R , 1TBS, BSD KNF.
Несрабатывание механизма автодополнения
В случае, если выражение, записанное на следующей строке, синтаксически может быть продолжением выражения на предыдущей строке, механизм автодополнения строк точками с запятой не срабатывает .
func()
['h1', 'h2'].forEach(function(t) {
handleTag(t)
})
В данном примере квадратные скобки на второй строке интерпретируются в качестве обращения к элементу массива, возвращаемого func(). Запятая в скобках трактуется как соответствующий оператор, возвращающий 'h2'. Таким образом, код преобразуется к следующему:
func()['h2'].forEach(function(t) {
handleTag(t);
});
В стандартах кодирования принято прописывать обязательность проставления точек с запятой даже в тех случаях, когда синтаксис языка позволяет их опускать .
Блоки и область видимости
Ещё одной особенностью ECMAScript по отношению к другим C-подобным языкам является то, что в данном языке блоки не образуют области видимости . Объявленные в блоке переменные распространяются на всю функцию, содержащую блок .
В данном участке кода имеет место повторное объявление переменной в выделенных строках:
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();
Кроме того, к переменной tmp , объявленной внутри первого из циклов (строка 4), в соответствии с синтаксисом языка вполне законно обратиться извне цикла (строка 10).
Из-за особенностей, связанных с областью видимости и блоками, в целях поддержания качества исходного кода рекомендуется объявлять переменные в начале функций .
Объявление переменных
Переменные определяются с помощью ключевых слов
var, let, const
. При объявлении переменная помещается в область видимости, соответствующую в случае
var
функции, а в случае
let, const
блоку кода. Если переменная объявляется вне функций, она помещается в глобальную область видимости. Создание переменной происходит при получении управления функцией с её объявлением. Или программой, если переменная глобальна. При создании переменной в ECMAScript она приобретает значение
undefined
. Если переменная объявлена с
инициализацией
, инициализация происходит не в момент создания переменной, а при выполнении строки с инструкцией
var
.
При раскомментировании выделенной строки на экран будет выводиться не number , а undefined :
var a = 42;
function foo() {
alert(typeof a);
// var a = 10;
}
foo();
При создании переменной она приобретает внутреннее свойство {DontDelete} и её невозможно удалить с помощью оператора
delete
. Исключение составляют переменные, объявленные в контексте
eval
.
Многие источники
декларируют возможность неявного объявления переменных в ECMAScript при осуществлении присваивания корректному идентификатору, не являющемуся формальным аргументом функции, без предварительного объявления с помощью
var
. Однако в терминологии спецификации языка в этом случае создаётся свойство глобального объекта, а не переменная
.
Фиксация в стандарте оформления кода необходимости обязательного объявления переменных до их использования (либо фиксация необходимости использовать пространства имён для всех глобальных объектов ) позволяет избегать трудноуловимых ошибок, предотвращая опасность взаимодействия одинаково названных переменных в разных участках кода .
Ключевые и зарезервированные слова
Следующие слова являются ключевыми в языке и не могут быть использованы как идентификаторы :
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
По сравнению с третьей редакцией спецификации
в пятой добавилось ключевое слово
debugger
с соответствующей инструкцией.
Следующие слова используются как ключевые слова в предложенных расширениях и поэтому являются зарезервированными для возможности адаптировать эти расширения :
class enum extends super const export import
При использовании строгого режима следующие слова рассматриваются как зарезервированные для использования в будущем :
implements let private public yield interface package protected static
Таким образом, по сравнению с третьей редакцией спецификации языка количество зарезервированных для использования в будущем слов существенно снизилось. Ранее их было 31 , и наличие большого количества ключевых и зарезервированных слов, большинство из которых не используется в языке, подвергалось критике .
Операторы
В ECMAScript имеются как операторы, использующие в качестве названий ключевые слова, так и операторы, использующие в качестве названий знаки препинания .
Классификация операторов
По убыванию приоритета операторы ECMAScript можно разбить в следующие группы:
-
.
(доступ к свойству),[]
(доступ к свойству),()
(вызов функции),new
(создание нового объекта), -
++
(инкремент),--
(декремент),-
(унарный минус),+
(унарный плюс),^
(поразрядное дополнение),!
(логическое дополнение),delete
(удаление свойства),typeof
(определение примитивного типа данных),void
(возврат неопределённого значения), -
*
(умножение),/
(деление),%
(остаток от деления), -
+
(сложение),-
(вычитание),+
(конкатенация строк), -
<<
(сдвиг влево),>>
(сдвиг вправо с расширением знакового разряда),>>>
(сдвиг вправо с дополнением нулями), -
<
(меньше),<=
(меньше или равно),>
(больше),>=
(больше или равно),instanceof
(проверка типа объекта),in
(проверка наличия свойства), -
==
(проверка на равенство),!=
(проверка на неравенство),===
(проверка на идентичность),!==
(проверка на неидентичность), -
&
(поразрядная конъюнкция ), -
^
(поразрядное сложение по модулю 2 ), -
|
(поразрядная дизъюнкция ), -
&&
(конъюнкция), -
||
(дизъюнкция), -
?:
( тернарная условная операция ), -
=
(присваивание),*=
,/=
,+=
,-=
,<<=
,>>=
,>>>=
,&=
,^=
,|=
(присваивание с операцией), -
,
(множественное вычисление) .
Операторы
++
,
--
,
-
,
+
,
~
,
!
,
delete
,
typeof
,
void
,
?:
,
=
,
*=
,
/=
,
+=
,
-=
,
<<=
,
>=
,
>>>=
,
&=
,
^=
,
|=
правоассоциативны (то есть для них
a op b op c
эквивалентно
a op (b op c)
). Остальные операторы ECMAScript левоассоциативны
.
По арности операторы ECMAScript делятся на следующие группы:
-
унарные
(
delete
,void
,typeof
,++
,--
,-
(унарный минус),+
(унарный плюс),^
,!
,new
) , -
бинарные
(
.
,[]
,()
,*
,/
,%
,+
(сложение),-
(вычитание),+
(конкатенация строк),<<
,>>
,>>>
,<
,<=
,>
,>=
,instanceof
,in
,==
,!=
,===
,!==
,&
,^
,|
,&&
,||
,=
,*=
,/=
,+=
,-=
,<<=
,>=
,>>>=
,&=
,^=
,|=
,,
), -
тернарные
(
?:
) , -
операторы, не имеющие фиксированного количества операндов (
()
) .
По положению знака операции относительно операндов операторы ECMAScript делятся на следующие группы:
-
префиксные (например,
new
,++
(префиксный инкремент), -
инфиксные (например,
+
,-
), -
постфиксные (например,
++
(постфиксный инкремент),--
(постфиксный декремент).
Также операторы классифицируются по типу операндов и по характеру осуществляемого действия.
Особенности операторов ECMAScript
В ECMAScript нет оператора, позволяющего проверить, относится ли свойство непосредственно к объекту или является унаследованным. Такая проверка осуществляется с помощью метода
hasOwnProperty()
. В связи с тем, что данный метод не является оператором, он может быть переписан любым другим свойством
.
Оператор
+
является единственным арифметическим оператором в языке, который
перегружен
для строковых аргументов. Если хотя бы один из операндов — строка,
+
действует как
конкатенатор
, в противном случае выполняется
сложение
.
В отличие от языков, где
void
является типом данных, в ECMAScript это оператор, возвращающий значение
undefined
.
Оператор
==
осуществляет проверку на равенство по
алгоритму
, состоящему из 10 шагов, подразумевающему в ряде случаев преобразование типов
, что, в конечном счёте, может привести к неочевидным результатам
.
Пример результатов работы
==
(во всех перечисленных случаях значением оператора
===
с теми же аргументами будет
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 являются
объектами
. Конструктор, с помощью которого они создаются —
Function()
. Функции, как и любые другие объекты, могут храниться в переменных, объектах и массивах, могут передаваться как аргументы в другие функции и могут возвращаться функциями. Функции, как и любые другие объекты, могут иметь свойства. Существенной специфической чертой функций является то, что они могут быть вызваны
.
Задание функций
В ECMAScript имеется два типа функций:
-
внутренние функции (например,
parseInt
), - функции, определённые в тексте программы.
Внутренние функции представляют собой встроенные объекты (см. ), не обязательно реализованные на ECMAScript .
В тексте программы именованную функцию в 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;");
Последний способ наименее предпочтителен, поскольку де-факто сводится к заданию функции с помощью выражения, но при этом порождает двойную интерпретацию кода (дополнительная интерпретация возникает при передаче кода в конструктор), что может негативно отразиться на производительности .
Первые два способа дают похожий, но не идентичный эффект. Усугубляет ситуацию то, что инструкция, использующаяся при задании функции, может выглядеть очень похоже на объявление функции: во-первых, за ключевым словом
function
может следовать идентификатор
, во-вторых, точка с запятой может быть опущена в силу механизма автодополнения строк точками с запятой
.
Пример:
// объявление функции
function sum(arg1, arg2) {
return arg1 + arg2;
}
// задание функции с помощью выражения
var sum2 = function sum(arg1, arg2) {
return arg1 + arg2;
}
function bar(){}; // использование объявления функции
(function bar(){}) // использование соответствующей инструкции
Наиболее существенной разницей между заданием функции с использованием объявления и заданием функции с помощью выражения является то, что в первом случае создание переменной и присваивание ей в качестве значения функции осуществляются до выполнения кода при входе в контекст исполнения. Во втором случае переменная получает значение инициализатора при выполнении оператора присваивания. При создании же переменной, осуществляемом при входе в контекст исполнения, она
инициализируется
значением
undefined
(подробнее см. в разделе
).
Пример, иллюстрирующий разницу в порядке выполнения кода:
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;
};
Объявлением функций не следует пользоваться внутри условных конструкций , хотя в Gecko-браузерах это обработается интуитивным образом за счёт реализованного механизма функций как инструкций .
Присваивания функций
Поскольку функции в 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
Если объявлено несколько функций с одинаковыми названиями, более поздние объявления перезаписывают ранние объявления .
Тем не менее, эффект перегрузки функций достижим.
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
. Он, в частности, позволяет воспользоваться индексированием для доступа к конкретным переданным аргументам
и свойством
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
.
Пример рекурсивного вычисления факториала:
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 не реализована хвостовая рекурсия , применяемая для оптимизации рекурсивных вызовов .
Функции обратного вызова
В ECMAScript функция представляет собой объект первого класса и может быть передана в другую функцию как аргумент. Если она при этом вызывается в функции, в которую передаётся, то её называют функцией обратного вызова (или callback-функцией ). Если при этом передаваемая функция не имеет имени, это анонимная функция обратного вызова ( анонимная callback-функция ) . Основные причины использования функций обратного вызова:
- избежание именования функции при оперировании с ней (способствует снижению числа глобальных переменных) ,
- делегирование вызова функции другой функции (способствует повышению выразительности кода) ,
- увеличение быстродействия ,
- упрощение оперирования с непродолжительными событиями .
Пример функции, возвращающей сумму от результатов выполнения переданной функции над аргументами:
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 присуща лексическая область видимости. Это означает, что область видимости определяется в момент определения функции (в отличие от динамической области видимости, при которой область видимости определяется в момент вызова функции) .
При объявлении функции последовательность областей видимости, относящихся ко вложенным функциям, сохраняется как составляющая состояния функции. То есть в процессе выполнения программы функции, обладающие доступом к локальным переменным объемлющих функций, сохраняют такой доступ на протяжении всего выполнения программы .
Механизм замыканий может использоваться для ограничения видимости переменных автономного участка программы с тем, чтобы не возникали конфликты имён при совместном с другим кодом использовании. Для этого код помещается в анонимную функцию, снабжаемую оператором вызова функции.
(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
Пример создания объекта, позволяющего осуществить доступ к свойству исключительно с помощью своих методов :
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
Пользуясь этим приёмом, можно использовать замыкание для эмуляции констант .
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 и допускают два вида синтаксиса: литеральный и объектный .
var literalWay = /pattern/flags;
var objectWay = new RegExp(pattern, flags);
В первом случае шаблон (
pattern
) и флаги (
flags
) указываются явно, не сопровождаясь дополнительными избыточными синтаксическими знаками: их разделителями служат
слеши
. Во втором случае шаблон и флаги должны представлять собой переменные, содержащие строковые значения, либо непосредственно строковые значения. Литеральная форма записи предпочтительнее тем, что не требует двойного
экранирования
метасимволов регулярных выражений, в отличие от объектной формы
.
В качестве флагов в ECMAScript могут использоваться следующие символы:
Флаг | Описание |
---|---|
g
|
г лобальный режим: шаблон применяется ко всем соответствиям в строке, работа регулярного выражения не останавливается после первого найденного соответствия шаблону |
i
|
и гнорирование : при поиске соответствий регистр символов шаблона и строки игнорируются |
m
|
м ногострочный режим: строка, содержащая символы перевода строки , трактуется как несколько строк, разделённых символами перевода строки; работа регулярного выражения осуществляется во всех строках |
Каждое регулярное выражение представляет собой объект со следующими свойствами:
Свойство | Тип | Описание |
---|---|---|
global
|
логический |
показывает, установлен ли флаг
g
|
ignoreCase
|
логический |
показывает, установлен ли флаг
i
|
multiline
|
логический |
показывает, установлен ли флаг
m
|
lastIndex
|
числовой | соответствует номеру позиции в строке, в которой обнаружилось совпадение с шаблоном в результате предыдущего применения регулярного выражения или 0, если регулярное выражение ранее не применялось |
source
|
строковый | строка, соответствующая шаблону регулярного выражения |
Кроме того, для регулярных выражений определены следующие методы:
Метод | Тип возвращаемого значения | Описание |
---|---|---|
exec(handledString)
|
объектный (массив) или
null
|
формирует массив подстрок, соответствующих заданному
шаблону
с учётом выставленных
флагов
.
null
, если никакая подстрока не соответствует
шаблону
|
test(handledString)
|
логический |
true
, если нашлась строка, соответствующая
шаблону
и
false
в противном случае
|
Объекты
Реализация в языке
Объекты ECMAScript представляют собой неупорядоченные коллекции свойств , каждое из которых имеет один или более атрибутов , которые определяют, как может быть использовано свойство — например, если в качестве значения атрибута ReadOnly установлена истина , то любая попытка выполняющегося ECMAScript-кода поменять значение этого свойства останется безрезультатной. Свойства представляют собой контейнеры , инкапсулирующие другие объекты, значения примитивных типов и методы .
Название | Описание |
---|---|
ReadOnly | Свойство является свойством только для чтения. Попытка поменять значение этого свойства, предпринятая в программе, останется безрезультатной. В некоторых случаях значение свойства с установленным атрибутом ReadOnly меняется в силу действий среды расширения языка, поэтому ReadOnly не следует понимать как неизменное |
DontEnum |
Свойство не перечисляется циклом
for-in
|
DontDelete | Попытки удалить это свойство будут проигнорированы |
Internal | Свойство является внутренним. Оно не имеет названия и к нему нельзя получить доступ с помощью аксессоров . Доступ к этим свойствам определяется реализацией языка. |
Объекты ECMAScript подразделяются на базовые (native) и объекты расширения (host). Под базовыми понимаются любые объекты, независимые от окружения, относящегося к расширению языка. Некоторые из базовых объектов являются встроенными (built-in): существующими с самого начала выполнения программы. Другие могут быть созданы, когда программа выполняется. Объекты расширения предоставляются расширением ECMAScript, а для ECMAScript это значит, что они входят в объектную модель документа или в объектную модель браузера .
Синтаксис
Для задания объектов может использоваться объектная и литеральная формы. Объектная форма задания объекта имеет синтаксис, аналогичный Java, но, в отличие от него, скобки в ECMAScript требуется использовать только при передаче аргументов в конструктор . Синтаксически следующие записи эквивалентны:
var obj1 = new Object();
var obj2 = new Object;
var obj3 = {};
Однако второй вариант использовать не рекомендуется . Дуглас Крокфорд рекомендует избегать и первого варианта, отдавая предпочтение литеральной форме, которую он считает большим достоинством языка .
Спецификация языка оперирует понятием свойства объекта, называя методом использующуюся в качестве свойства объекта функцию .
Каждый объект в языке имеет следующие свойства:
Название | Краткое описание |
---|---|
constructor |
Функция, использованная для создания объекта (в примерах выше это
Object()
)
|
hasOwnProperty(propertyName) | Показывает, существует ли данное свойство в объекте (не в его прототипе ) |
isPrototypeOf(object) | Определяет, находится ли объект в цепи прототипов объекта-аргумента |
propertyIsEnumerable(propertyName) |
Показывает, является ли свойство с данным названием перечислимым в цикле
for-in
|
toString() | Возвращает представление объекта в виде строки |
valueOf() |
Возвращает значение
this
. Если же объект является результатом вызова конструктора
объекта расширения
, значение
valueOf()
зависит от реализации
. Зачастую в качестве возвращаемого значения выступает значение примитивного типа, соответствующее объекту. Как правило, результат данного метода совпадает с результатом
toString()
. Объекты, созданные с помощью конструктора
Date()
— яркий пример, где результаты
toString()
и
valueOf()
не совпадают
.
|
Доступ к свойствам объекта осуществляется использованием точечной и скобочной записи:
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
}; // использование литеральной формы
Подходы к созданию объектов
Создание объектов описанным в предыдущем разделе способом может быть непрактичным из-за необходимости дублировать код . Если в программе происходит манипуляция с большим количеством однотипных объектов, разработчик имеет возможность выбрать одну из используемых в языке техник :
- фабрика объектов
- функция, создающая объект и возвращающая его в качестве своего значения,
- конструктор
-
функция, использующая ключевое слово
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
Для каждой из составляющих объекта можно рассматривать наследование. При наследовании интерфейса родителя без того, чтобы потомок использовал функциональность предка, говорят о наследовании интерфейса. При наследовании состояния осуществляется наследование объектом-потомком структуры данных объекта-предка. При наследовании функциональности речь идёт о наследовании вместе с интерфейсом и кода методов. Как правило, это влечёт необходимость организации наследования состояния, что делает разумным объединение наследования состояния и наследования функциональности в наследование реализации .
В отношении ECMAScript неприменимо лишь наследование интерфейсов, поскольку функции в языке не имеют сигнатур .
О возможностях, предоставляемых языком для организации наследования, можно судить, например, по приводимому списку из двенадцати разных способов организации наследования.
ECMAScript 6
Принятие ES6 устранило многие классы проблем JavaScript .
Примечания
- ↑ Dr. Axel Rauschmayer. // . — First Edition. — O’Reilly Media, 2014. — P. 41. — ISBN 978-1-449-36503-5 . 10 мая 2015 года.
- — 2006.
- 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 .
- 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. Типы данных и значения // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. —66. — ISBN 5-93286-103-7 .
- Jensen S., Møller A., Thiemann P. (англ.) // Lecture Notes in Computer Science : Материалы конф. / The 16th International Static Analysis Symposium (SAS 2009), Лос-Анджелес, США, 9 – 11 августа 2009. — Springer Berlin / Heidelberg, 2009. — Vol. 5673 . — P. 238 — 255 . — ISBN 978-3-642-03236-3 . (недоступная ссылка)
- Crockford D. A.3. Semicolon Insertion // JavaScript: The Good Parts. — 2008. — P. 102. — ISBN 978-0-596-51774-8 .
- Dr. Axel Rauschmayer. // . — First Edition. — O’Reilly Media, 2014. — P. 378. — ISBN 978-1-449-36503-5 . 10 мая 2015 года.
- Dr. Axel Rauschmayer. // . — First Edition. — O’Reilly Media, 2014. — P. 41. — ISBN 978-1-449-36503-5 . 10 мая 2015 года.
- ↑ Crockford D. A.2. Scope // JavaScript: The Good Parts. — 2008. — P. 36. — ISBN 978-0-596-51774-8 .
- Дэвид Флэнаган. 4.3.1. Отсутствие блочной области видимости // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. —71. — ISBN 5-93286-103-7 .
- ↑ Сошников, Дмитрий (27 июня 2009). Дата обращения: 6 ноября 2009. 18 февраля 2012 года.
- Дэвид Флэнаган. 4.2. Объявление переменных // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. . — ISBN 5-93286-103-7 .
- Koch Peter-Paul. Implicit variable declaration // / Editor: Wendy Sharp. — 1st ed. — New Riders Press, 2006. — 528 p. — ISBN 978-0-321-42330-6 .
- 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 .
- 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 .
- Easttom C. Variable Declaration // Advanced Javascript. — 3rd ed. — USA: Wordware Publishing, Inc, 2008. — 81 — 83 p. — ISBN 1-59822-033-0 .
- Keith J. Variables // DOM Scripting: Web Design with JavaScript and the Document Object Model. — 1st ed. — USA: Wordware Publishing, Inc, 2005. — 18 — 20 p. — ISBN 1590595335 .
- Koch Peter-Paul. Chapter 5. Core. Section D. Variables // / Editor: Wendy Sharp. — 1st ed. — New Riders Press, 2006. — 528 p. — ISBN 978-0-321-42330-6 .
- Crockford D. A.4. Reserved Words // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8 .
- Дэвид Флэнаган. 5.2. Обзор операторов // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. —79. — ISBN 5-93286-103-7 .
- Дэвид Флэнаган. 5.2.4 Ассоциативность операторов // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. . — ISBN 5-93286-103-7 .
- Дэвид Флэнаган. 5.2.1 Количество операндов // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. . — ISBN 5-93286-103-7 .
- Дэвид Флэнаган. 5.10.8 Оператор вызова функции // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. . — ISBN 5-93286-103-7 .
- Дэвид Флэнаган. 5.2.2 Тип операндов // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. . — ISBN 5-93286-103-7 .
- Crockford D. A.13. hasOwnProperty // JavaScript: The Good Parts. — 2008. — P. 107. — ISBN 978-0-596-51774-8 .
- Crockford D. A.8. + // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8 .
- Crockford D. B.12. void // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8 .
- Crockford D. B.1. == // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8 .
- ↑ Crockford D. 4.1. Function Objects // JavaScript: The Good Parts. — 2008. — P. 26. — ISBN 978-0-596-51774-8 .
- ↑ 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 .
- Сошников, Дмитрий (26 июня 2009). Дата обращения: 12 октября 2010. 16 октября 2010 года.
- Juriy "kangax" Zaytsev. (англ.) . — Статья, детально описывающая разницу между заданием функции с помощью объявления и заданием функции с помощью выражения. Дата обращения: 19 октября 2009. Архивировано из 19 июня 2009 года.
- и др. (англ.) . Functions and function scope . — Описание деталей реализации функций как выражений в контексте объявлений внутри условий. Дата обращения: 19 октября 2009. Архивировано из 14 октября 2008 года.
- Crockford D. 4.4. Arguments // JavaScript: The Good Parts. — 2008. — P. 31. — ISBN 978-0-596-51774-8 .
- Crockford D. 4.8. Recursion // JavaScript: The Good Parts. — 2008. — P. 35. — ISBN 978-0-596-51774-8 .
- ↑ 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.
- Crockford D. 4.11. Callbacks // JavaScript: The Good Parts. — 2008. — P. 40. — ISBN 978-0-596-51774-8 .
- ↑ Дэвид Флэнаган. 8.8. Область видимости функций и замыкания // = JavaScript. The Definite Guide / Перевод А. Киселева. — 5-е изд. — СПб. : , 2008. — С. —163. — ISBN 5-93286-103-7 .
- Crockford D. 4.10. Closure // JavaScript: The Good Parts. — 2008. — 170 p. — ISBN 978-0-596-51774-8 .
- Harmes R., Diaz D. Constants // Pro JavaScript™ Design Patterns. — USA: Apress, 2008. — P. 37, 38. — ISBN 1-59059-908-X .
- ↑ 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 .
- ↑ 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 .
- Crockford D. JSON // JavaScript: The Good Parts. — 2008. — P. 136. — ISBN 978-0-596-51774-8 .
- ↑ 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 .
- Кузнецов, Михаил . Издательство «Открытые системы» (11 декабря 2002). Дата обращения: 1 ноября 2009. 17 февраля 2010 года.
- 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.
- . Дата обращения: 17 марта 2017. 20 декабря 2016 года.
- . Дата обращения: 17 марта 2017. 10 июня 2017 года.
- . Дата обращения: 17 марта 2017. 20 декабря 2016 года.
- . Дата обращения: 17 марта 2017. 20 декабря 2016 года.
Стандарты ECMAScript
- 7th edition (June 2016) (англ.)
- (June 1999) (англ.)
- (June 2001) (англ.)
- 2nd edition (December 2005) (англ.)
Спецификации ECMAScript
- . ecma-international.org (июнь 2023). Дата обращения: 18 сентября 2023. 21 августа 2023 года.
- TC39. Brief History // . — 5th ed. — 2009. 12 апреля 2015 года. . Дата обращения: 8 декабря 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 4.3. Definitions // . — 5th ed. — 2009. — P. 4. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 8.5. The Number Type // . — 5th ed. — 2009. — P. 29. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 8. Types // . — 3rd ed. — 1999. — P. 24. 11 апреля 2016 года.
- ↑ TC39. 8. Types // . — 5th ed. — 2009. — P. 28. (недоступная ссылка)
- TC39. 12. Statements // . — 5th ed. — 2009. — P. 86—97. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 7.9. Automatic Semicolon Insertion // . — 5th ed. — 2009. — P. 25—28. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 12. Statements // . — 3rd ed. — 1999. — P. 61—71. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 12.2. Variable Statement // . — 5th ed. — 2009. — P. 87, 88. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 10.2.2. Eval Code // . — 3rd ed. — 1999. — P. 39. (недоступная ссылка)
- TC39. 7.6.1.1. Keywords // . — 5th ed. — 2009. — P. 18. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 7.5.2. Keywords // . — 3rd ed. — 1999. — P. 13—14. (недоступная ссылка)
- ↑ TC39. 7.6.1. Reserved Words // . — 5th ed. — 2009. — P. 18, 19. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 7.5.3. Future Reserved Words // . — 3rd ed. — 1999. — P. 15. (недоступная ссылка)
- TC39. 11.4. Unary Operators // . — 5th ed. — 2009. — P. 70—72. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 11.6.1 The Addition operator ( + ) // . — 5th ed. — 2009. — P. 74, 75. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 11.9.3. The Abstract Equality Comparison Algorithm // . — 5th ed. — 2009. — P. 80, 81. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 4.3. Definitions // . — 5th ed. — 2009. — P. 4—7. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 13 Function Definition // . — 5th ed. — 2009. — P. 97, 98. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 12.2 Variable Statement // . — 5th ed. — 2009. — P. 87, 88. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 10.6. Arguments Object // . — 5th ed. — 2009. — P. 60—62. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- ↑ TC39. 15.10. RegExp (Regular Expression) Objects // . — 5th ed. — 2009. — P. 179—196. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 4.2. Language Overview // . — 5th ed. — 2009. — P. 2—4. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. 8.6.1. Property attributes // . — 3rd ed. — 1999. — P. 25, 26. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
- TC39. Properties of the Object Prototype Object // . — 5th ed. — 2009. — P. 114—116. 12 апреля 2015 года. . Дата обращения: 11 ноября 2009. Архивировано 12 апреля 2015 года.
Комментарии
- Только в отношении do-while
-
Одним
обратным слешем
экранируются метасимволы строк (например,
\t
). Для экранирования метасимволов регулярных выражений используется двойной обратный слеш (например,\\s
)
Стандарты оформления кода JavaScript
- ↑ Crockford, Douglas (англ.) . Douglas Crockford's JavaScript . — Стандарт оформления кода JavaScript Дугласа Крокфорда. Дата обращения: 5 октября 2009. 18 февраля 2012 года.
- ↑ (англ.) . Echo Web Framework . NextApp, Inc. — Стандарт оформления кода JavaScript, принятый для Echo Web Framework. Дата обращения: 5 октября 2009. 18 февраля 2012 года.
- Amaram, Rahul (англ.) . Echo Web Framework . — Стандарт оформления кода JavaScript Рауля Амарама. Дата обращения: 5 октября 2009. 18 февраля 2012 года.
- ↑ Komenda, Klaus (англ.) . Сайт австрийского веб-разработчика Клауса Коменда . — Стандарт оформления кода JavaScript Клауса Коменда. Дата обращения: 5 октября 2009. 18 февраля 2012 года.
- (англ.) . GNOME. — Стандарт оформления кода JavaScript в GNOME. Дата обращения: 24 декабря 2009. 18 февраля 2012 года.
Ссылки
- (англ.)
- (рус.)
- (рус.)
- , статья на IBM DeveloperWorks
- (англ.) , John Resig
- — Status, process, and documents for ECMA262 (англ.) от 13 августа 2016 на Wayback Machine
- 2021-06-27
- 1