According to my tests it is always left-to-right
>> console.log( console.log(1), console.log(2) );
1
2
undefined undefined
but I can't find the relevant section confirming this in the ECMAScript standard.
All the operators in JavaScript evaluate their operands left-to-right, including the function call operator. First the function to call is evaluated then the actual parameters in left-to-right order.
Section 11.2.3 is the relevant spec section.
11.2.3 Function Calls
...
2 Let func be GetValue(ref).
3 Let argList be the result of evaluating Arguments, producing an internal list of argument values (see 11.2.4).
...
and you can see that the ArgumentList production is left-recursive
11.2.4 Argument lists
...
The production ArgumentList : ArgumentList , AssignmentExpression is evaluated as follows
and ArgumentList is evaluated before AssignmentExpression in the following verbiage..
Under EcmaScript 3 some of the comparison operators (<, <=, >, >=) evaluated right to left since a<=b was defined in terms of !(b<a), but that was widely recognized as a spec error, major interpreters did not implement it that way, and it was fixed in EcmaScript 5.
From the language spec:
11.8.5 The Abstract Relational Comparison Algorithm # Ⓣ
The comparison x < y, where x and y are values, produces true, false, or undefined (which indicates that at least one operand is NaN). In addition to x and y the algorithm takes a Boolean flag named LeftFirst as a parameter. The flag is used to control the order in which operations with potentially visible side-effects are performed upon x and y. It is necessary because ECMAScript specifies left to right evaluation of expressions. The default value of LeftFirst is true and indicates that the x parameter corresponds to an expression that occurs to the left of the y parameter’s corresponding expression. If LeftFirst is false, the reverse is the case and operations must be performed upon y before x. Such a comparison is performed as follows:
It's defined here:
The production ArgumentList : ArgumentList , AssignmentExpression is
evaluated as follows:
Let precedingArgs be the result of evaluating ArgumentList.
Let ref be the result of evaluating AssignmentExpression.
Let arg be GetValue(ref).
Return a List whose length is one greater than the length of precedingArgs and whose items are the items of precedingArgs, in
order, followed at the end by arg which is the last item of the new
list.
Read here: http://es5.github.com/#x11.2.4
When a function is invoked, the passed-in arguments are evaluated from left to right.
For historical interest, also see section 4.2 Evaluation Order of JavaScript 1.1 Language Specification (Brendan Eich, C. Rand Mckinney, 11/18/96).
In a function or constructor call, one or more argument expressions
may appear within the parentheses, separated by commas. Each argument
expression is fully evaluated before any part of any argument
expression to its right is evaluated.
Related
Which expression inside if statement will be evaluated faster?
var test = true;
if( test == true ) {...}
OR
var test = true;
if( test ) {...}
Only got info about The Abstract Equality Comparison Algorithm and The Strict Equality Comparison Algorithm
Wanted to know more about how Truthy/Falsy values are evaluated.
Any help is appreciated.
Thanks
The second example might be a bit faster (but since JS is today usually first compiled into a bytecode and only then evaluated, it's probable the generated bytecode will be the same in both cases).
It all starts with The if statement. Its first step (and the only step that will differ in your examples) is to evaluate the expression within parentheses. In the second example, the expression is immediately evaluated to itself (true). In the first example, The Abstract Equality Comparison Algorithm, as you mentioned, will be used. It will make a few steps and return true from step 1.e.
In practice, I doubt the difference will be measurable.
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).
I realize that this is improper syntax, but why is JavaScript ignoring the first number and giving a response instead of breaking?
let myArray = [1,2,3,4]
myArray[0,1] // 2
myArray[1,3] // 4
myArray[3,0] // 1
It's not improper syntax.
That's just the comma operator in action.
From docs:
The comma operator evaluates each of its operands (from left to right) and returns the value of the last operand.
For instance, [1,2][1,2], perhaps bizarrely enough, will return undefined.
Why?
The second [ is interpreted by the compiler to be the array subscript operator, because JavaScript's semantics don't allow two arrays to be next to each other.
Thus, the second 1,2 must be an expression that evaluates to an index. 1,2 results in the first operand being evaluated, followed by the second, which is what's returned. So it uses index 2, which of course doesn't exist in that array, and we get undefined.
This is because it is evaluating the comma operator in each set of square brackets.
I am looking at these lines of code from here:
if (callback)
callback(sig || graph);
I have never see vertical "or" bars in a javascript method call. What do they mean? Do they pass the "true" parameter (i.e. sig or graph)? Do they pass the defined parameter? I have never seen that syntax before.
This is the logical OR operator in JS (and most other languages). It is defined in the spec at 11.11. As noted in the spec, expressions on either side will be evaluated first and the logical OR is left-to-right associative. Note that evaluation of the operands follows standard ToBoolean semantics from section 9.2, so [null, undefined, 0, ''] all count as falsy.
Unlike most languages, JS returns the left operand if it is truthy or the right operand otherwise. This behavior has been covered before in a number of SO questions, but is worth noting as most languages simply return true or false. This behavior is often used to provide default values to otherwise undefined variables.
The Logical OR operator (||) is an operator that returns its first or second operand depending on whether the first is truthy. A "truthy" value means anything other than 0, undefined, null, "", or false.
This operator uses short-circuiting, meaning if the first expression is truthy, then the second expression is not evaluated and the first operand is returned immediately. This is akin to the Logical AND operator (&&), which does the opposite: if the first operand is falsey, it returns it, otherwise it returns the second expression.
It means 'or' (http://www.w3schools.com/js/js_comparisons.asp) So if(sig OR graph)
BE CAREFUL you can 'short circuit' your code using this.
example :
If (foo || foo2)
if foo is true, then JavaScript wont even test foo2 at all, it just skips it.
It passes whichever evaluates as true, or sig if both are true.
The double pipe (||) represents OR in JS. In simple words, either this or that is True. It requires any of the sides true to get a True result.
For example:
var x = 8;
var y = 'c';
x >= 8 || y === 'a'
The left side of the double pipe returns True where the right side is False. Thus, the result is True.
The operator || means OR.
If either sig or graph are true or not null variables, callback function will receive a true argument.
According to my tests it is always left-to-right
>> console.log( console.log(1), console.log(2) );
1
2
undefined undefined
but I can't find the relevant section confirming this in the ECMAScript standard.
All the operators in JavaScript evaluate their operands left-to-right, including the function call operator. First the function to call is evaluated then the actual parameters in left-to-right order.
Section 11.2.3 is the relevant spec section.
11.2.3 Function Calls
...
2 Let func be GetValue(ref).
3 Let argList be the result of evaluating Arguments, producing an internal list of argument values (see 11.2.4).
...
and you can see that the ArgumentList production is left-recursive
11.2.4 Argument lists
...
The production ArgumentList : ArgumentList , AssignmentExpression is evaluated as follows
and ArgumentList is evaluated before AssignmentExpression in the following verbiage..
Under EcmaScript 3 some of the comparison operators (<, <=, >, >=) evaluated right to left since a<=b was defined in terms of !(b<a), but that was widely recognized as a spec error, major interpreters did not implement it that way, and it was fixed in EcmaScript 5.
From the language spec:
11.8.5 The Abstract Relational Comparison Algorithm # Ⓣ
The comparison x < y, where x and y are values, produces true, false, or undefined (which indicates that at least one operand is NaN). In addition to x and y the algorithm takes a Boolean flag named LeftFirst as a parameter. The flag is used to control the order in which operations with potentially visible side-effects are performed upon x and y. It is necessary because ECMAScript specifies left to right evaluation of expressions. The default value of LeftFirst is true and indicates that the x parameter corresponds to an expression that occurs to the left of the y parameter’s corresponding expression. If LeftFirst is false, the reverse is the case and operations must be performed upon y before x. Such a comparison is performed as follows:
It's defined here:
The production ArgumentList : ArgumentList , AssignmentExpression is
evaluated as follows:
Let precedingArgs be the result of evaluating ArgumentList.
Let ref be the result of evaluating AssignmentExpression.
Let arg be GetValue(ref).
Return a List whose length is one greater than the length of precedingArgs and whose items are the items of precedingArgs, in
order, followed at the end by arg which is the last item of the new
list.
Read here: http://es5.github.com/#x11.2.4
When a function is invoked, the passed-in arguments are evaluated from left to right.
For historical interest, also see section 4.2 Evaluation Order of JavaScript 1.1 Language Specification (Brendan Eich, C. Rand Mckinney, 11/18/96).
In a function or constructor call, one or more argument expressions
may appear within the parentheses, separated by commas. Each argument
expression is fully evaluated before any part of any argument
expression to its right is evaluated.