I was reading the EcmaScript6 specifications and in the Arithemetic operator section ( http://www.ecma-international.org/ecma-262/5.1/#sec-11.6.1 ) its mentioned like this
AdditiveExpression :
MultiplicativeExpression
AdditiveExpression + MultiplicativeExpression
AdditiveExpression - MultiplicativeExpression
What does this mean ?
An expression of multiplication or division.
See Section 11.5
From MDN article on Expressions and operators:
An expression is any valid unit of code that resolves to a value.
So in this case a MultiplicativeExpression is any unit of code that results in multiplication. Most commonly it involves the * operator.
You can read the Annotated EcmaScript as it contains some helpful links on top of the spec.
It means that the ECMA specification is written in Martian. Or by Martians. Or for Martians. I've never been too sure, exactly.
Err, but more helpfully, section 11.6.1 explains how the "addition operator" (what we primitive humans usually call the plus sign or just "+" or "+/-") should treat the result of statements of addition, subtraction, multiplication, division, modulus division, and even string concatenation.
In the header you quote, the writers are calling attention to the various statement types they are trying to define, which is both the simple and more complex case of multiple statements that must be combined (as with the last two lines).
Later in the section it defines how 'hinting' should be handled, in what cases the script should treat variables as numbers instead of strings, etc.
It's just a really esoteric way to put it.
Related
According to Ecma-262, prefix increment and decrement operators are defined as:
UpdateExpression :
LeftHandSideExpression ++
LeftHandSideExpression ‐‐
++ UnaryExpression
‐‐ UnaryExpression
This is surprising, both that the postfix and prefix operators are defined in the same rule, and that it's ++ UnaryExpression when surely a unary expression in general is not actually a valid argument for the update operators.
It would seem cleaner and more logical to define the prefix increment and decrement operators in UnaryExpression itself, along with the other prefix operators, and other C syntax languages do this, e.g. the C standard section 6.5.3 defines unary-expression to include the prefix update operators along with the others.
Why does JavaScript define these operators the way it does?
Why does JavaScript define these operators the way it does?
It's mostly historical, as so many other oddities in the spec.
It would seem cleaner and more logical to define the prefix increment and decrement operators in UnaryExpression itself, along with the other prefix operators, and other C syntax languages do this
In fact, that's how it was defined for many years, in ES5.1 and ES6. It's simple, and has one syntactic production per precedence level (PostfixExpression being the next-tighter one), and was probably directly inherited from the C or Java grammar when JS was conceived.
Surely a unary expression in general is not actually a valid argument for the update operators
In C, -- -- x is actually valid, so that's why the prefix increment and decrement operator expressions contain another UnaryExpression. Of course, it would throw an exception when trying to evaluate the expression, but parsing it would work fine in ES5.
ES6 then added the concept of early errors, and increment and decrement operations now required a valid assignment target expression upon parsing. This was not encoded in the syntactical productions though.
It is surprising that the postfix and prefix operators are defined in the same rule
This definition is new in ES7. It changed with this commit that introduced the exponentiation operator, where the PostfixExpression was renamed to UpdateExpression and the prefix operators were moved into the rule. Some change like that was necessary because the ** operator allows an update expression, but not a UnaryExpression as its first argument (because unary minus, as in -x ** 3, was deemed too ambiguous).
If I try to write
3.toFixed(5)
there is a syntax error. Using double dots, putting in a space, putting the three in parentheses or using bracket notation allows it to work properly.
3..toFixed(5)
3 .toFixed(5)
(3).toFixed(5)
3["toFixed"](5)
Why doesn't the single dot notation work and which one of these alternatives should I use instead?
The period is part of the number, so the code will be interpreted the same as:
(3.)toFixed(5)
This will naturally give a syntax error, as you can't immediately follow the number with an identifier.
Any method that keeps the period from being interpreted as part of the number would work. I think that the clearest way is to put parentheses around the number:
(3).toFixed(5)
You can't access it because of a flaw in JavaScript's tokenizer. Javascript tries to parse the dot notation on a number as a floating point literal, so you can't follow it with a property or method:
2.toString(); // raises SyntaxError
As you mentioned, there are a couple of workarounds which can be used in order make number literals act as objects too. Any of these is equally valid.
2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first
To understand more behind object usage and properties, check out the Javascript Garden.
It doesn't work because JavaScript interprets the 3. as being either the start of a floating-point constant (such as 3.5) or else an entire floating-point constant (with 3. == 3.0), so you can't follow it by an identifier (in your case, a property-name). It fails to recognize that you intended the 3 and the . to be two separate tokens.
Any of your workarounds looks fine to me.
This is an ambiguity in the Javascript grammar. When the parser has got some digits and then encounters a dot, it has a choice between "NumberLiteral" (like 3.5) or "MemberExpression" (like 3.foo). I guess this ambiguity cannot be resolved by lookahead because of scientific notation - should 3.e2 be interpreted as 300 or a property e2 of 3? Therefore they voluntary decided to prefer NumberLiterals here, just because there's actually not very much demand for things like 3.foo.
As others have mentioned, Javascript parser interprets the dot after Integer literals as a decimal point and hence it won't invoke the methods or properties on Number object.
To explicitly inform JS parser to invoke the properties or methods on Integer literals, you can use any of the below options:
Two Dot Notation
3..toFixed()
Separating with a space
3 .toFixed()
Write integer as a decimal
3.0.toFixed()
Enclose in parentheses
(3).toFixed()
Assign to a constant or variable
const nbr = 3;
nbr.toFixed()
So I was fooling around with the new exponentiation operator and I discovered you cannot put a unary operator immediately before the base number.
let result = -2 ** 2; // syntax error
let result = -(2 ** 2); // -4
let x = 3;
let result = --x ** 2; // 4
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.
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.
I understand this was made an error by design. I don't understand this design decision. Who's really going to be surprised that -x ** 2 is negative? This follows not only other mainstream programming languages but a mathematical notation that has been in common use for hundreds of years and is taught to every high school algebra student.
In Javascript '1'+ 2 is '12' and '1'-2 is -1 but -1**2 raises an error because it could be ambiguous? Help me understand this design decision.
I don't understand this design decision.
Read more about it at https://esdiscuss.org/topic/exponentiation-operator-precedence, https://esdiscuss.org/topic/power-operator-why-does-2-3-throws, https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-09/sept-23.md#exponentiation-operator and https://github.com/rwaldron/tc39-notes/blob/master/es7/2015-09/sept-24.md#exponentiation-operator.
Who's really going to be surprised that -x ** 2 is negative?
Enough people to matter. Some relevant quotes from the above resources:
"making ** bind tighter than unary operators would break x**-2. And making it sometimes tighter and sometimes looser would be too confusing and lead to other opportunities for precedence inversion." - Waldemar Horwat
"Given the conflict between the history of ** in other languages, [and] the general pattern that unary binds tighter than binary, any solution at this point will confuse many people." - Mark S. Miller
"acknowledge the prospect of significant whitespace: -x**2 === -(x ** 2) and -x ** 2 === (-x) ** 2" - Alexander Jones
"The problem is, however rare unary minus before an exponentiation expression may be, the lack of superscript-with-smaller-font sugests that - binds tighter than **. And indeed apart from dot (a special form whose right operand must be a lexical identifier-name) and square brackets (which isn't an infix operator per se), unary operators bind tighter than binary in JS as in C and other C-derived languages." - Brendan Eich
"For math it seems obvious that -52. But for -5 ** 2, because of the whitespace around the infix operator. Even without space, - seems to be part of the literal." - Dave Herman
[Regarding programming language precedence], "effectively zero people have an intutition about this from other languages. Agree people have an itutition that ** is the exponentiation operator. But people usually try to avoid dark corners so they never develop an intuition for negative bases." - Dave Herman
In Javascript '1'+ 2 is '12' and '1'-2 is -1 but -1**2 raises an error because it could be ambiguous?
Well they put considerably more effort in the design of extensions to the language today :-) It's the best solution that they could reach consensus for.
If you evaluate 1|0,2|0 in JavaScript, you'll get 2.
If you evaluate 1|0+','+2|0, you'll get 1.
I cannot make sense of this.
The binary bitwise operators (including |) bind less tightly than the addition operator +. Thus
1|0+','+2|0
is really
1|(0+','+2)|0
which is
1|('0,2')|0
which is
1|0|0
which is 1. (The string "0,2" is converted to an integer; as a number it's NaN, but because NaN is a floating-point concept it turns into 0 when forced to be an integer.)
edit — as to the first expression, 1|0,2|0, that involves the JavaScript comma operator. The comma operator allows a list of separate, essentially independent (other than through side-effects) expressions to be "glued together" into something the parser will recognize as a single expression. When evaluated, each expression will be computed as it normally would be, but the value of the overall expression is just the value of the last one in the list. Thus, 1|0,2|0 will first cause 1|0 to be evaluated, but that result is thrown away and the overall value is just that of 2|0.
The comma operator is common to many languages that derive their expression syntax from C. (For all I know, C got it from somewhere else; it's hardly a revolutionary concept.) Because such languages allow for an expression — just one expression — to appear in several interesting grammatical situations, and because expressions can (and often do) have side effects, it's sometimes handy to be able to jam several separate expressions into a spot where the language really wants only one. That said, there are often cleaner and better ways to do things. In JavaScript, I would personally prefer to use an immediately-invoked function. It's more typing and probably a little worse for performance reasons, but I think it's a lot cleaner because it allows for an isolated namespace for temporary variables and more involved logic.
You need to look at an operator precedence table to make sense of this.
The expression 1|0,2|0 has bitwise-or at a higher precedence than the comma operator, so it's equivalent to (1|0), (2|0). The comma operator evaluates both operands and returns the second one, so you get the value of (2|0). That value is 2.
The expression 1|0+','+2|0 has addition at a higher precedence than bitwise-or, so it's equivalent to 1|(0+','+2)|0. The result of 0+','+2 is "0,2", which is not numerical, so it evaluates to NaN in numerical operations. It is coerced to 0 in bitwise-or, so that leaves 1|0|0, and the result of that is 1.
From MDN:
The comma operator evaluates both of its operands (from left to right)
and returns the value of the second operand.
Thus, in 1|0,2|0, first the two expressions 1|0 and 2|0 are evaluated from left to right and then the result of the last expression (2|0) is returned. 1|0 === 1 and 2|0 === 2, so the result of the last expression is 2 and that's returned.
In 1|0+','+2|0, the comma appears in a string literal which is concatenated with 0 and 2. The whole thing is evaluated as followed:
( 1 | ( (0+',')+2 ) ) | 0
( 1 | ( '0,'+2 ) ) ) | 0 (number + string = string concatenation)
( 1 | '0,2' ) | 0 (string + number = string concatenation)
( 1 | NaN ) | 0 (bitwise OR needs number operands. 0,2 fails to be converted, giving NaN instead)
1 | 0 (bitwise OR only deals with integers, so the floating-point NaN is cast to 0)
1
Just curious. I did a program in C, with quite an amount of bitwise operations for a variable which defines access controls for a page. I wanna be able to do the same in Javascript only. How can i accomplish this ordeal?
Any help in bit-tweaking in Javascript will help. Remember no costly functions allowed.
JavaScript has the usual assortment of bitwise operators, |, &, ~, etc.; details in the specification.
The following sections will be particularly useful:
Section 11.4.8: Bitwise NOT (~)
Section 11.7: Bitwise Shift Operators (<< and >>)
Section 11.10: Binary Bitwise Operators (| and &)
Note that JavaScript's numbers are all floating point (see Section 8.5, The Number Type, in the specification), but the bitwise operations are defined in terms of integers. So for instance, the definition of the bitwise NOT operator:
11.4.8 Bitwise NOT Operator ( ~ )
The production UnaryExpression : ~ UnaryExpression is evaluated as follows:
1. Let expr be the result of evaluating UnaryExpression.
2. Let oldValue be ToInt32(GetValue(expr)).
3. Return the result of applying bitwise complement to oldValue. The result is a signed 32-bit integer.
Any decent implementation will be able to handle these efficiently, avoiding unnecessary conversions from Number to internal integer and back.
JavaScript has bitwise operators like other languages. Bitwise operators are, by definition, efficient. You should be able to replicate all the bitwise operations performed in your C program in JS as well.
http://www.eecs.umich.edu/~bartlett/jsops.html