Почему работает "+ + b", но "a ++ b" нет?
Я играл с разными вещами, вроде этого
var a = 1, b = 2;
alert(a + - + - + - + - + - + - + - + b); //alerts -1
и я мог бы удалить пробелы, и он все равно будет работать.
a+-+-+-+-+-+-+-+b
Затем я попробовал
a + + b
Он запускался и оценивался до 3, но когда я удалял пробелы, (a++b
) он не запускался, и у него было предупреждение, которое гласило: "Confusing plusses."
Я могу понять, что в таких случаях, как
a+++++b
который можно интерпретировать как любое из следующих
(a++) + (++b)
(a++) + +(+b)
a + +(+(++b))
a + +(+(+(+b)))
что это будет путать.
Но в случае
a++b
единственный допустимый способ интерпретировать это, насколько я могу судить,
a + +b
Почему не работает a++b
?
Ответы
Ответ 1
Парсер Javascript является жадным (он соответствует самому длинному действительному оператору каждый раз), поэтому он получает оператор ++
от a++b
, делая:
(a++) b
что является недопустимым. Когда вы помещаете пробелы a + + b
, синтаксический анализатор интерпретирует это следующим образом:
(a) + (+b)
который действителен и работает как три.
Подробнее об этом см. в статье в Википедии Максимальный munch.
Ответ 2
Он читает a++
, затем встречает b
и не знает, что с ним делать.
Ответ 3
Это b/c разности унарных операторов.
"a + + b" is the same as "a + (+b)"
"a++b" is the same as "(a++) _ b" <--- there is a missing operator where the _ is
Ответ 4
Правила оценки оператора Javascript для оператора приращения ++
не имеют лево-правой ассоциативности. Это означает, что a++b
можно интерпретировать как a++ b
или a ++b
в зависимости от конкретной реализации. В любом случае, это синтаксическая ошибка, так как у вас есть 2 переменные, один унарный оператор и ничто не объединяет две переменные.
В практическом плане:
a = 1
b = 2;
a++ b; -> 2 2
a ++b; -> 1 3
Что означает 1 3
как JS-код?
Ответ 5
Большинство парсеров языка программирования пытаются получить самый длинный фрагмент текста, который имеет смысл, поэтому, когда Javascript видит:
[a][][][][]
"variable a" - это имеет смысл, пусть видит следующий символ:
[a][+][][]
"будет добавлять в varaible a" - это имеет смысл, пусть видит следующий символ:
[a][+][+][]
"будет использовать переменную post-increment a" - это имеет смысл, пусть видит следующий символ,
[a][+][+][b]
Это не имеет смысла. У меня есть два выражения (a ++) и (b) и между ними нет инфиксного оператора.
Если вы сделаете это a+ +b
, он не найдет оператора ++
, и он будет работать как a + + b
.
Ответ 6
Самое длинное совпадение. Он говорит, что парсер должен принимать во внимание самый длинный токен, начиная слева направо (я полагаю, что грамматика Javascript - слева направо). Поэтому просто примените это правило, и вы получите ответ.
Парсер начнет с левой стороны и будет делать a +, + и b отдельные токены в случае "a + + b" (из-за пробела между ними). В случае "a ++ b" он применяет самое длинное правило совпадения и будет создавать символы ++ и b в качестве токена. a ++ b как выражение не делает никакого смыслового смысла, поэтому он не будет скомпилирован.
Ответ 7
Ответ заключается в том, что ++ - это оператор, а также +, и что + + - это два + оператора, а не оператор ++.
Хотя это не Javascript, С++ имеет схожую забаву с операторами + и ++. Это было исследовано в одном из "Гуру недели" назад.