ECMAScript

您所在的位置:网站首页 合欢皮的毒性大吗 ECMAScript

ECMAScript

2024-02-24 00:52| 来源: 网络整理| 查看: 265

ECMAScript Класс языка язык программирования общего назначения[d] Появился в июнь 1997 Автор Брендан Эйх и Ecma International Разработчик Брендан Эйх Расширение файлов .es[2] Выпуск ECMAScript 2023[Спецификация 1] (июнь 2023; 8 месяцев назад (2023-06)) Система типов утиная Диалекты JavaScript, JScript, ActionScript, JScript .NET, QtScript Испытал влияние Self[1], Си, Scheme[1], Perl[1], Python, Java[1], AWK[1] Повлиял на Objective-J Сайт ecma-international.org (англ.)

ECMAScript — встраиваемый расширяемый не имеющий средств ввода-вывода язык программирования, используемый в качестве основы для построения других скриптовых языков[3].

ECMAScript стандартизирован международной организацией ECMA в спецификации ECMA-262. Расширения языка: JavaScript, JScript и ActionScript.

Содержание 1 История 2 Семантика и синтаксис 2.1 Типы данных 2.2 Инструкции 2.2.1 Автодополнение строк точками с запятой 2.2.1.1 Инструкции, меняющие смысл при использовании перевода строки внутри[Спецификация 8] 2.2.1.2 Несрабатывание механизма автодополнения 2.2.2 Блоки и область видимости 2.2.3 Объявление переменных 2.3 Ключевые и зарезервированные слова 2.4 Операторы 2.4.1 Классификация операторов 2.4.2 Особенности операторов ECMAScript 2.5 Функции 2.5.1 Задание функций 2.5.2 Присваивания функций 2.5.3 Перегрузка функций 2.5.4 Рекурсия 2.5.5 Функции обратного вызова 2.5.6 Замыкания 2.6 Регулярные выражения 2.7 Объекты 2.7.1 Реализация в языке 2.7.2 Синтаксис 2.8 Подходы к созданию объектов 2.9 Особенности наследования в ECMAScript 2.10 ECMAScript 6 3 Примечания 4 Стандарты ECMAScript 4.1 Спецификации ECMAScript 4.2 Комментарии 4.3 Стандарты оформления кода JavaScript 5 Ссылки История[править | править код]

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

Семантика и синтаксис[править | править код] Типы данных[править | править код]

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

числовой (англ. Number), строковый (англ. String), логический (англ. Boolean), нулевой (англ. Null), неопределённый (англ. Undefined)[Спецификация 3].

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

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

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

объектный (англ. Object).

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

ссылочный (англ. Reference), списочный (англ. List), заключительный (англ. Completion). (новый[Спецификация 5][Спецификация 6]) описатель свойства (англ. Property Descriptor), (новый[Спецификация 5][Спецификация 6]) идентификатор свойства (англ. Property Identifier), (новое[Спецификация 5][Спецификация 6]) лексическое окружение (англ. Lexical Environment), (новая[Спецификация 5][Спецификация 6]) запись окружения (англ. Environment Record).

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

Инструкции[править | править код]

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

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

while () for ([]; []; []) for (; []; []) for ( 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 − (новое[Спецификация 9]) Отладчик англ. Debugger debugger − Автодополнение строк точками с запятой[править | править код]

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

Инструкции, меняющие смысл при использовании перевода строки внутри[Спецификация 8][править | править код] Унарный постфиксный ++ Унарный постфиксный -- Продолжение Прерывание Возврат Генерация исключения

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

return { status: "complete" };

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

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

Несрабатывание механизма автодополнения[править | править код]

В случае, если выражение, записанное на следующей строке, синтаксически может быть продолжением выражения на предыдущей строке, механизм автодополнения строк точками с запятой не срабатывает[9].

func() ['h1', 'h2'].forEach(function(t) { handleTag(t) })

В данном примере квадратные скобки на второй строке интерпретируются в качестве обращения к элементу массива, возвращаемого func(). Запятая в скобках трактуется как соответствующий оператор, возвращающий 'h2'. Таким образом, код преобразуется к следующему:

func()['h2'].forEach(function(t) { handleTag(t); });

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

Блоки и область видимости[править | править код]

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

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

function foo() { var sum = 0; for (var i = 0; i > (сдвиг вправо с дополнением нулями), = (больше или равно), instanceof (проверка типа объекта), in (проверка наличия свойства), == (проверка на равенство), != (проверка на неравенство), === (проверка на идентичность), !== (проверка на неидентичность), & (поразрядная конъюнкция), ^ (поразрядное сложение по модулю 2), | (поразрядная дизъюнкция), && (конъюнкция), || (дизъюнкция), ?: (тернарная условная операция), = (присваивание), *=, /=, +=, -=, =, >>>=, &=, ^=, |= (присваивание с операцией), , (множественное вычисление)[21].

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

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

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

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

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

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

Особенности операторов ECMAScript[править | править код]

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

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

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

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

Пример результатов работы == (во всех перечисленных случаях значением оператора === с теми же аргументами будет 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 являются объектами[30][31]. Конструктор, с помощью которого они создаются — Function(). Функции, как и любые другие объекты, могут храниться в переменных, объектах и массивах, могут передаваться как аргументы в другие функции и могут возвращаться функциями. Функции, как и любые другие объекты, могут иметь свойства. Существенной специфической чертой функций является то, что они могут быть вызваны[30].

Задание функций[править | править код]

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

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

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

В тексте программы именованную функцию в 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;");

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

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

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

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

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

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

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

Присваивания функций[править | править код]

Поскольку функции в 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

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

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

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[Спецификация 22]. Он, в частности, позволяет воспользоваться индексированием для доступа к конкретным переданным аргументам[31][35] и свойством length, хранящем количество фактически переданных аргументов, что может быть полезно при применении парадигмы обобщённого программирования.

function sum() { var res = 0; for (var i = 0; i


【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3