4

If I run the following code on Firefox I get an error:

new Number.toString;

But according to MDN https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence new Number should evaluate first. So the table is not correct I think.

Let us take a look at MSDN: http://msdn.microsoft.com/en-us/library/z3ks45k7(v=vs.94).aspx . Above the table is written that operators are evaluated from left to right. But:

a=1;
b=a=2;

Now b has the value 2 which suggest evaluation from right to left. So also this precedence table is not correct.

Can anyone give me a correct table?

rene
  • 39,748
  • 78
  • 111
  • 142
Marco de Wit
  • 2,518
  • 16
  • 21

2 Answers2

6

according to https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence$revision/510297#Table new Number should evaluate first. So the table is not correct I think.

The new Operator is complicated. Let's check the official language grammar: It does occur in two manifestations:

MemberExpression := new MemberExpression Arguments | …
NewExpression := new NewExpression | …

The latter, where is called without arguments, does indeed have a lesser precedence than the property accessors - so that your expression evaluates as new (Number.toString). However, when new is called with arguments (parenthesis), then it does have a greater precedence than a CallExpression and is equal to a property accessor, in which case they'd evaluate left-to-right. Indeed, the MDN table should make this more clear.

Let us take a look at MSDN: http://msdn.microsoft.com/en-us/library/z3ks45k7(v=vs.94).aspx . Above the table is written that operators are evaluated from left to right.

This is definitely wrong. Operator associativity is not always left-to-right, most obvious at the assignment operators as in your example. The MDN table states this correct. Also, MSDN seems to oversimplify the precedence of postfix operators.

Can anyone give me a correct table?

Try my new revision of MDN's table.

Bergi
  • 572,313
  • 128
  • 898
  • 1,281
  • The MDN table had been correct in [this revision](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Operator_Precedence$revision/418427), but then became incorrect. I have fixed it now, please check if you can understand the new table (and whether I still have overlooked something) – Bergi Jan 16 '14 at 14:13
  • What about `new new Function` ? Associativity is needed now I think. – Marco de Wit Jan 16 '14 at 17:19
  • Yes, it is right-to-left associative: `new (new (Function)))`. Did I forgot that? – Bergi Jan 16 '14 at 17:25
  • I meant `new new Function()()` . I use it on a daily basis. ;) – Marco de Wit Jan 16 '14 at 17:26
  • That's `new (new (Function)())()`. `new` with arguments rules them all - I'd say by precedence, I don't know how to apply the concept of "associativity" to such an expression. It's a [context-free grammar](https://en.wikipedia.org/wiki/Context-free_grammar) production after all. – Bergi Jan 16 '14 at 18:13
  • Isn't that right to left then? Because the right `new` is done first? Maybe it is better to add a footnote to `new` in the table which warns about the trickyness. – Marco de Wit Jan 17 '14 at 08:54
  • Can I ask a question ? If for example, a function call is more precedent than the increment operator, why does this example print `11` out instead of `10`: `var a = 10; function foo() { return a; } console.log((a++, foo()));` – doubleOrt Dec 02 '17 at 21:13
  • Moreover, is `new Foo("whatever")` an example that illustrates the difference in precedence between `new` with and without arguments (because `new Foo("whatever")` is evaluated entirely instead of `(new Foo)("whatever")`? If not, what is an example ? – doubleOrt Dec 02 '17 at 22:11
  • @Taurus The order of evaluation in `(a++, foo())` is defined by the comma operator and has nothing to do with operator precedence (which is really pretty unambigous here). Precedence only is relevant in a case like `--foo()` (which, of course, causes an exception no matter which way it would be parsed). Regarding `new`, yes that might be an example. – Bergi Dec 02 '17 at 23:31
  • @Bergi I don't know but to me it doesn't seem unambiguous, in that MDN page `,`s are in the same list with `++` and function calls, so I would expect something like "function call > `++` > ," to get into play in this example, I don't know, all this feels a bit awkward, it feels like I am missing out an important part on Operator Precedence which neither Kyle Simpson (I will have to double-check) nor MDN is covering. Or it looks like I have forgotten to look at an important part of this, I don't know what it is. I would expect the same thing to happen with this: (will continue) – doubleOrt Dec 02 '17 at 23:46
  • var a = 10; `function foo() { return a; } console.log(a++ == foo()); // false` I would expect this to return `true` instead, not before knowing about operator precedence, but only after reading that MDN list) since a function call has the highest precedence, and then increment and then `==`. – doubleOrt Dec 02 '17 at 23:48
  • 1
    @Taurus I'll say it again: Operator precedence (whether `a+b*c` means `(a+b)*c` or `a+(b*c)`) has nothing to do with operand evaluation order (which is always left-to-right in JavaScript: `a` then `b` then `c`). – Bergi Dec 02 '17 at 23:50
  • @Bergi I shall respond after thinking about that statement (your comment) for a while. – doubleOrt Dec 02 '17 at 23:51
  • @Bergi So, in JavaScript `foo() + foo() * 10;` is done like `[result of foo, done first] + [result of foo, done second] * 10` and then it applies the precedence rules only after evaluating all the operands (from left to right), or in other words, after everything is a value ? – doubleOrt Dec 02 '17 at 23:59
  • my last statement (_everything converted to a value before precedence rules..._) is obviously not true for conditionals and such, operands to the right are evaluated only if the conditions pass, e.g `10 == 20 && 20 == foo() // never evaluated`. I am talking more in context of the `foo() + foo() * 10` example. – doubleOrt Dec 03 '17 at 00:08
  • @Bergi Kyle Simpson only makes a warning ("left-to-right is JavaScript's default") in the context of "Associativity", BTW. – doubleOrt Dec 03 '17 at 00:09
  • It does apply the precedence rules to form an abstract syntax tree, and then evaluates that from outside in. All binary operators that always evaluate both their arguments will do so left-to-right. Conditional operators still go outside in and start on the left. – Bergi Dec 03 '17 at 10:05
0

Here is MDN's full operator precedence table, available at your link:

enter image description here

CertainPerformance
  • 313,535
  • 40
  • 245
  • 254