Это не оператор.
Во всех смыслах этого слова - не один. Это было огромным заблуждением с тех пор, как оно было введено, и, несмотря на распространенное мнение, это не так, и есть несколько объективных замечаний:
- Это не подходит под определение оператора
- Его нельзя использовать в качестве оператора
- Спецификация языка подразумевает, что это не оператор
Следует отметить, что расширенный синтаксис бывает разных «разновидностей», используется в разных контекстах и обычно упоминается под разными именами при использовании одного и того же знака препинания. Синтаксис распространения — это, по сути, общий термин для применения знака препинания ...
, и см. отличный ответ Феликса Клинга, подробно описывающий все употребления и названия. Дополнительные пояснения об использовании этих лиц приведены в дополнительном ответе.
Что такое оператор?
Семантически, в контексте ECMAScript, операторы — это просто встроенные функции, которые принимают аргументы и вычисляют одно значение, записанное в префиксной, инфиксной или постфиксной нотации и обычно с символическими именами, такими как +
или /
. Из Википедии:
Проще говоря, выражение, включающее оператор, оценивается каким-то образом, и результирующее значение может быть просто значением (r-значение) или может быть объектом, допускающим присваивание (l-значение).
Например, оператор +
приводит к такому значению, как 2, которое является правосторонним выражением, а оператор .
приводит к объекту, допускающему присваивание, например foo.bar
, левостороннему выражению.
На первый взгляд знак препинания ...
1 выглядит как префиксный унарный оператор:
const baz = [foo, ...bar];
Но проблема с этим аргументом в том, что ...bar
не дает единственного числа; он распространяет итерируемые элементы bar
один за другим. То же самое касается аргументов распространения:
foo(...bar);
Здесь foo
получает отдельные аргументы от итерируемого bar
. В foo
передаются отдельные значения, а не одно значение. Он не подходит под определение оператора, поэтому он им не является.
Почему не оператор?
Еще один момент, который следует отметить, заключается в том, что операторы должны быть автономными и возвращать одно значение. Например:
const bar = [...foo];
Как уже упоминалось, это работает хорошо. Проблема возникает, когда вы пытаетесь сделать это:
const bar = ...foo;
Если бы синтаксис расширения был оператором, последний работал бы нормально, поскольку операторы оценивают выражение до единственного значения, а расширение не работает, поэтому оно не работает. Синтаксис расширения и аргументы расширения работают только в контексте массивов и вызовов функций, потому что эти структуры получают несколько значений, предоставленных элементами или аргументами расширения массива. Вычисление нескольких значений выходит за рамки возможностей оператора.
Что говорят стандарты?
Полный список операторов приведен в пунктах с §12.5 по §12.15 в Спецификации языка ECMAScript 2015., спецификация, в которой представлен ...
, но не упоминается ...
. Также можно сделать вывод, что это не оператор. Два основных случая, упомянутых в этом ответе, в которых синтаксис распространения находится в производстве, для вызовов функций (аргументы расширения) или литералы массива (синтаксис расширения) описаны ниже:
ArrayLiteral :
[ Elisionopt ]
[ ElementList ]
[ ElementList , Elisionopt ]
ElementList :
Elisionopt AssignmentExpression
Elisionopt SpreadElement
ElementList , Elisionopt AssignmentExpression
ElementList , Elisionopt SpreadElement
Elision :
,
Elision ,
SpreadElement :
... AssignmentExpression
А для вызовов функций:
CallExpression :
MemberExpression Arguments
Arguments :
( )
( ArgumentList )
ArgumentList :
AssignmentExpression
... AssignmentExpression
ArgumentList , AssignmentExpression
ArgumentList , ... AssignmentExpression
По этим постановкам можно сделать вывод, что «оператора» спреда не существует. Как упоминалось ранее, операторы должны быть автономными, как в const bar = ...foo
, и оценивать одно единственное значение. Синтаксис языка предотвращает это, а это означает, что синтаксис распространения никогда не предназначался для автономного использования. Это расширение инициализаторов массивов и вызовов функций, расширение их грамматики.
Зачем распространять «синтаксис»?
Синтаксис, определенный в Википедии:
В информатике синтаксис компьютерного языка — это набор правил, определяющих комбинации символов, которые считаются правильно структурированным документом или фрагментом на этом языке.
Синтаксис — это, по сути, «форма» языка, правила, которые определяют, что является законным, а что нет в отношении того, как должен выглядеть код и как код должен быть написан. В этом случае грамматика ECMAScript специально определяет знак препинания ...
, чтобы он появлялся только в вызовах функций и литералах массива в качестве расширения — это правило, определяющее комбинацию символов (...foo
), которые вместе считаются допустимыми, поэтому < em>синтаксис аналогично тому, как стрелочная функция (=>
) является не оператором, а синтаксисом2.
Называть ...
оператором неправильно. Оператор – это встроенная функция, которая принимает аргументы (операнды) в виде префикса, инфикса или постфикса, и возвращает ровно одно значение. ...
, удовлетворяя первым двум условиям, не удовлетворяет последнему. ...
, напротив, является синтаксисом, поскольку он конкретно и явно определен в грамматике языка. Таким образом, «оператор распространения» объективно правильнее называть «синтаксисом расширения».
1 Термин "знак пунктуации" относится к знакам препинания. в спецификациях ECMAScript 2015 и более поздних. Эти символы включают синтаксические компоненты и операторы и являются пунктатором языка. ...
сам по себе является знаком препинания, но термин «расширенный синтаксис» относится ко всему применению знака препинания.
2 =>
сам по себе является знаком препинания, как и ...
, но я имею в виду синтаксис функции стрелки, применение знака препинания =>
((…) => { … }
), так же как синтаксис расширения относится к применению знака препинания ...
.
person
Community
schedule
05.07.2017