57

Executing it in the browser console it says SyntaxError: Unexpected token **. Trying it in node:

> -1**2
...
...
...
...^C

I thought this is an arithmetic expression where ** is the power operator. There is no such issue with other operators.

Strangely, typing */ on the second line triggers the execution:

> -1**2
... */
-1**2
  ^^
SyntaxError: Unexpected token **

What is happening here?

Boann
  • 44,932
  • 13
  • 106
  • 138
psmith
  • 1,742
  • 15
  • 18
  • It is supposed to be supported in ECMA2016. http://2ality.com/2016/02/exponentiation-operator.html – web-nomad Apr 22 '17 at 07:57
  • 1
    Try this instead: `(-1)**2`. – Darin Dimitrov Apr 22 '17 at 07:58
  • 22
    firefox says: `SyntaxError: unparenthesized unary expression can't appear on the left-hand side of '**'` - you must be using Chrome - the error message is totally useless at best – Jaromanda X Apr 22 '17 at 08:00
  • 1
    same goes for `+1**2` – Medet Tleukabiluly Apr 22 '17 at 08:05
  • @JaromandaX In my Firefox 49 on OSX i got `SyntaxError: expected expression, got '*'`. – psmith Apr 22 '17 at 11:39
  • @psmith - update :p – Jaromanda X Apr 22 '17 at 11:41
  • @JaromandaX The error message was the same in Firefox 51 as well, but from Firefox 52 i also get very clear error what you posted above. – psmith Apr 22 '17 at 12:28
  • 2
    @psmith, that is because FireFox implemented the `**` operator [in version 52](https://developer.mozilla.org/en-US/docs/Web/JavaScript/New_in_JavaScript/ECMAScript_Next_support_in_Mozilla). The syntax error you got in older versions reflects that `**` was not supported at all (nothing related to precedence or parentheses). – trincot Apr 22 '17 at 13:38
  • 3
    @JaromandaX Why vendetta with chrome ? – A---B Apr 22 '17 at 19:24
  • 30
    JS never ceases to amaze me. `'1'+2` is `'12'` and `'1'-2` is `-1` but `-1**2` raises an error because it could be ambiguous? Wow. – Eric Duminil Apr 22 '17 at 21:47
  • Any idea about the second part of my question? Why Node asks for more input (i.e. showing the `...`) after typing `-1**2`? – psmith Apr 23 '17 at 00:20
  • 1
    @A---B - it's an *opinion* - why is it important enough for you to ask? – Jaromanda X Apr 23 '17 at 01:10
  • 1
    @JaromandaX Would you rather people be using IE? xD – jpmc26 Apr 23 '17 at 04:29
  • 1
    @EricDuminil All the old WTFs are exactly why they're trying to be very careful with new features! – curiousdannii Apr 23 '17 at 05:16
  • @JaromandaX, yea, but it could be worse, it could be [any other browser other than chrome](https://cvedetails.com) – gman Apr 23 '17 at 06:23
  • @gman According to their [top 50 flawed products](https://www.cvedetails.com/top-50-products.php?year=0), IE has had fewer known flaws than Firefox and Chrome. – Cees Timmerman Apr 23 '17 at 08:20
  • 1
    Ie had had 11 versions . Vs 50+. So divide the number of flaws by the number of versions ... – Jaromanda X Apr 23 '17 at 08:32
  • @curiousdannii: So now we're stuck with old, lazy WTFs and new, overzealous WTFs. The best of both worlds! :) – Eric Duminil Apr 23 '17 at 08:50
  • @CeesTimmerman, if you pick any particular full year you'll see chrome has less than 1/10th as many code execution bugs as any other browser. Let's pick 2016. FF has 26x more code execution bugs, Safari has 15x, Edge has 37x, – gman Apr 23 '17 at 10:39
  • @gman Do you mean JavaScript code execution bugs? That'd be because it has a different JavaScript engine, and as we know from PHP "works" =/= "works correctly". If you mean native code execution bugs it's because Edge combines the worse parts of IE with the instability of the Metro UI, Safari runs an old version of Apple WebKit (whereas Chrome uses a more beta version) and Firefox is used by the sort of people who play with everything (i.e. developers) more than most other browsers. – wizzwizz4 Apr 23 '17 at 15:06
  • @CeesTimmerman Look again. IE has two separate entries. "IE" and "Internet Explorer." The sum of the two (1481 total) actually brings it up to *number 3* in that list, just topping both Chrome and Firefox. I'm also of the opinion that the reason those applications are so high is simply because they're used so much and are so important; this means that people are more likely to look for and find vulnerabilities. – jpmc26 Apr 24 '17 at 06:16

2 Answers2

80

Executing it in the browser console says SyntaxError: Unexpected token **.

Because that's the spec. Designed that way to avoid confusion about whether it's the square of the negation of one (i.e. (-1) ** 2), or the negation of the square of one (i.e. -(1 ** 2)). This design was the result of extensive discussion of operator precedence, and examination of how this is handled in other languages, and finally the decision was made to avoid unexpected behavior by making this a syntax error.

  • 5
    Interesting decision from operator precedence perspective, since power always comes before addition/subtraction. Thus `-1**2` is `-1`, not `1`. – Adriaan Apr 22 '17 at 11:41
  • Thanks, i had this thought that the error is to avoid confusion about the operator precedence, but dropped the idea because the error message is just so misleading. – psmith Apr 22 '17 at 11:49
  • 7
    @Adriaan: Not true. In regular mathematics the negativity of numbers is not usually treated as subtraction. In fact minus one square is treated as the square of minus one not the minus of one square so it is 1 not -1. In other words, `-1` does not mean `0-1` but `1 * -1` – slebetman Apr 22 '17 at 11:57
  • 56
    @slebetman `-1^2` is never treated as `(-1)^2` in mathematics. Have you ever seen how polynomials are written? We'd have to write `-(x^2)+bx+c` instead of the normally used `-x^2+bx+c` if we follow your claim. And, more generally, `a(x^2)+bx+c` instead of `ax^2+bx+c`. – Ruslan Apr 22 '17 at 12:36
  • And here we have yet another reminder that the way mathematicians do maths and how processors do maths are often different. One cannot make assumptions without knowing how a language functions – Darren H Apr 22 '17 at 13:13
  • @slebetman "but `1 * -1`" In that case, exponentiation still takes precedence. – code_dredd Apr 22 '17 at 16:49
  • 33
    This comment thread seems to exactly underline why it was removed: to prevent confusion. My immediate reaction was to interpret it as `(-1)**2` because unary generally takes precedence over binary, but of course it also makes sense to have it be interpreted as `-(1**2)` for consistency with mathematics. Dropping the feature means that instead of writing something and having it work a different way, you'll just get a syntax error and look up the reasoning (on StackOverflow, perhaps!) instead, then make precedence explicit--no more confusion. – Schism Apr 22 '17 at 17:15
  • @Ruslan arguably, we should just always be writing `0 - x² + b·x + c` or else something more like `⌋x²⌊ + b·x + c`, instead of employing the `-` symbol in two hard-to-reconcile ways. – leftaroundabout Apr 22 '17 at 20:08
  • @leftaroundabout or, if we really decide to switch to more explicit notation, why not just use Reverse Polish notation? Then all ambiguity will vanish naturally. – Ruslan Apr 22 '17 at 20:25
  • @Ruslan: I hope you were being sarcastic. If not – _I_ would say the standard maths convention of using infix operators is pretty good and expresses the tree nature of algebraic expressions better than polish notation (reverse- or Lisp S-expressions). _Because_ it is so good, it would make sense to stop the jeopardization of its consistency which the addition of an extra rule that only applies to the (admittedly very important) special case of `-` brings about. – leftaroundabout Apr 22 '17 at 20:35
  • 4
    @Schism: Your point would make sense with any language but Javascript. JS never cared about consistency, surprising results or weird implicit conversions. In JS, I'd expect `-1**2` to return `NaN`, `[]` or `''`, but surely not raise an exception. – Eric Duminil Apr 22 '17 at 21:57
  • 2
    Incredible decision to make it a syntax error. It is *much* harder to detect as a syntax error and give this very specific error message than it is to actually implement it either way. – user207421 Apr 23 '17 at 01:22
  • @EJP: That's not a very specific error message at all; it's a generic syntax error message like you'd get for almost any other syntax error. It's also not particularly hard to write the grammar to exclude expressions of the form `-thing**thing`. They just made the LHS an UpdateExpression instead of a UnaryExpression. – user2357112 supports Monica Apr 23 '17 at 03:10
  • 8
    @EricDuminil: Javascript used to be like that, but people are doing their best not to make new design decisions in the spirit of the old. – user2357112 supports Monica Apr 23 '17 at 03:11
  • So why is `-1 ** 2` not allowed but `-100 / -100 * 10` is? – Salman A Dec 30 '19 at 19:59
40

From the documentation on MDN:

In JavaScript, it is impossible to write an ambiguous exponentiation expression, i.e. you cannot put a unary operator (+/-/~/!/delete/void/typeof) immediately before the base number.

The reason is also explained in that same text:

In most languages like PHP and Python and others that have an exponentiation operator (typically ^ or **), the exponentiation operator is defined to have a higher precedence than unary operators such as unary + and unary -, but there are a few exceptions. For example, in Bash the ** operator is defined to have a lower precedence than unary operators.

So to avoid confusion it was decided that the code must remove the ambiguity and explicitly put the parentheses:

(-1)**2

or:

-(1**2) 

As a side note, the binary - is not treated that way -- having lower precedence -- and so the last expression has the same result as this valid expression:

0-1**2

Exponentiation Precedence in Other Programming Languages

As already affirmed in above quote, most programming languages that have an infix exponentiation operator, give a higher precedence to that operator than to the unary minus.

Here are some other examples of programming languages that give a higher precedence to the unary minus operator:

trincot
  • 211,288
  • 25
  • 175
  • 211
  • +1 Thanks for the link to a human readable documentation. torazaburo's link to the spec is a bit hard to understand. – psmith Apr 22 '17 at 11:59
  • 21
    When language designers cite bash as a precedent, something stupid is about to happen. –  Apr 22 '17 at 14:08
  • 7
    @WumpusQ.Wumbley "designers" is a very strong word when talking about people responsible for JS. If you've never tried it before, look at the results for `[]+[]`, `[]+{}`, `{}+[]` and `{}+{}`. – Eric Duminil Apr 22 '17 at 22:02
  • 4
    @EricDuminil I just tried this. My flabber has never been so completely gasted before. – cyberbit Apr 25 '17 at 19:18
  • 1
    @cyberbit: Credits go to [Gary Bernhardt](https://www.destroyallsoftware.com/talks/wat). – Eric Duminil Apr 25 '17 at 20:46