Как работает оператор группировки JavaScript?
Как работает оператор группировки JavaScript?
1 + 2;
(1 + 2);
function(){ return 1} + "text"; // SyntaxError
(function(){return 1} + "text");
Учитывая приведенный выше код, у меня есть следующие вопросы:
- Почему
1 + 2;
работает без синтаксической ошибки, тогда как function(){ return 1} + "text"
вызывает SyntaxError?
- Как оператор группировки в
(function(){return 1} + "text")
исправляет ошибку синтаксиса?
Ответы
Ответ 1
Когда function
находится в начале инструкции, он рассматривается как начало определения имени функции, которое должно выглядеть следующим образом:
function someName() { return 1; }
Это выражение, а не выражение, поэтому оно не может использоваться как часть более крупного выражения.
Фактически, это недействительно, чтобы иметь этот оператор без имени. Вы получаете синтаксическую ошибку:
function() { return 1}
сам по себе.
Но когда вы помещаете его после скобки, это уже не начало инструкции, поэтому это выражение функции, которое возвращает функцию как значение. Затем он может использоваться как суб-выражение в более крупном выражении.
Это не оператор группировки, который делает это, просто тот факт, что он не в начале инструкции. Например, вы также можете написать:
var foo = function() { return 1 } + "text";
Ответ 2
1+2;
- это то, что работает на большинстве языков с синтаксисом C-inspired. Одним из видов разрешенных операторов в Javascript является оператор, который просто содержит выражение. Это позволяет операторам, которые содержат только вызов функции, например foo();
или присваивание, такие как x=5;
. Да, присваивания в Javascript считаются выражениями вместо операторов, поэтому вам разрешено снимать себя в ногу и назначать задание в условном выражении if (классическая ошибка =
vs ==
). В конце концов, компилятору было бы сложно запретить бесполезные выражения-выражения, такие как 1+2;
, сохраняя при этом foo()
и x = 5;
.
Объект function(){}
vs (function(){})
- это привидение Javascript. Javascript имеет разные правила в грамматике для "операторов объявления функций" и "выражений функций" . В первом примере функция анализируется как оператор, который нельзя добавить к другим вещам. Во втором случае в скобках функция анализируется как выражение, которое позволяет добавлять ее к другим вещам.
Вот почему "self invoking function pattern" всегда добавляет пару скобок в анонимную функцию.
(function(){
...
}())
Ответ 3
Вопрос о операторе группировки() или операторе приоритета.
Предварительное примечание: скобки, используемые в функции [name]() {} ", являются частью синтаксиса функции (idem для функции invokation), а не оператора группировки.
Оператор группировки имеет наивысший приоритет над любым другим оператором, именно потому, что его роль заключается в изменении приоритета содержащегося в нем выражения (т.е. в скобках). Это означает, что выражение в круглых скобках полностью оценивается до того, как его значение будет использовано в остальной части выражения. В дальнейшем:
(1+2); // strictly equivalent to 1+2;
// because nothing more in the expression
или
var x = ("3"==3)? "ok":"ko"; // grouping operator is useless as well
... но (как указано в Barmar'answer):
синтаксис "function() {return 1;}", когда put(), управляется оператором группировки, и рассматривается как выражение, которое должно быть выполнено до использования в полном заявлении, и есть 2 последствия:
- разрешена анонимная функция, поскольку мы находимся в выражении функции;
- выражение функции должно иметь аргументы, предоставляемые его параметрам, и если вы ожидаете возвращаемого значения (note2) - вторая пара скобок является обязательной, чтобы содержать аргументы или аргументы без аргументов.
(function() {return 1;}());
Примечание2: в исходном вопросе упоминался пример:
(function(){return 1} + "text"); //-> function(){return 1}text
как не возвращающий синтаксическую ошибку: он правильный, но возвращает код функции как строковое значение, а не значение 1, за которым следует строка "текст". Зачем? потому что для выполнения не были предусмотрены скобки. Мы должны написать:
(function(){return 1}()) + "text"; //-> 1text