Javascript evaluation order for operators - javascript

Which of the following expressions will always precede left to right in all browsers(particularly IE6+, F3+, Opera 9+, Chrome)? For example the window should always alert first function then second function. In C they always suggest not to depend on the order of the evaluation of expressions. Is the same true for JavaScript or is Operator Precedence consistent?
function first(){
alert('first function');
return 0;
}
function second(){
alert('second function');
return 23;
}
first() + second();
first() - second();
first() * second();
first() / second();
first() < second();
first() > second();
Using mozilla it appears function evaluation should be consistent in all browsers, but obviously the standard isn't always followed.
Testing
After some test on browsershots.org it appears all browsers follow the standard.
Generally
The exception is when relying on the the valueOf method in javascript. ValueOf definitely appears to be called backwards in specific cases for google chrome.
// The following alerts second then first in google chrome
first.valueOf = function(){alert('first');};
second.valueOf = function(){alert('second');};
first > second;

ECMAScript 5 specifies the order of evaluation of the operands for all operators. In the case of every operator in your code snip the evaluation order is left-to-right. I'm not sure anyone could answer about the behavior of all browsers though.
Edit: See also ECMAScript 3. Evaluation order is defined the same way.

Evaluating the expression into a value (e.g. involving a function call) is always done left to right.
However, once you are comparing two values, they are not converted into primitives in order to do the actual comparison in a left to right fashion. Try the following in Chrome, for example:
var l = {valueOf: function() { alert("L"); }};
var r = {valueOf: function() { alert("R"); }};
l < r; //alerts "L", then "R"
l > r; //alerts "R", then "L"

Operator precedence and order of evaluation are two entirely different things. In the expression "sqrt(9) + sqrt(16) * sqrt(25)" it is misleading to say that "the multiplication is done first.". It is correct to say "multiplication takes precedence over addition.".
The operations are:
sqrt(9)
sqrt(16)
sqrt(25)
4 * 5
3 + 20
The first three could be done in any order, or -- gasp -- simultaneously if you have a four-core CPU and a browser that can take advantage of it. 1 must be done before 5, 2 and 3 must be done before 4, and 4 must be done before 5. There are no other guarantees.
In the expression "a && (b / a)", JavaScript guarantees that a is evaluated first and b / a is not evaluated if a is zero. Many other languages including Fortran do not guarantee this, and can get a division-by-zero exception.

I'm not sure what your use-case is, but this might be an option:
function add() {
var retval = 0;
for (var i = 0; i < arguments.length; i++) {
retval += arguments[i];
}
return retval;
}
function echoNum(num) {
alert("Num: " + num);
return num;
}
alert("Result: " + add(echoNum(1), echoNum(2)));

Related

Javascript inline if statement

I had a bit of a weird result in the javascript console. I was trying to look for an alternative (more readable) version of the ternary operator, just for fun. Typing:
{ if(3===4) {5} else {6} }
Evaluates in my console to 6, but for some reason, I can not assign it to a variable, so running:
let a = { if(3===4) {5} else {6} }
Does not let me store it to the variable directly. So my main question is, if this block is returning something, why can't I assign it?
The fact that blocks (and other statements) return values isn't accessible to your code. Consoles can see the result, and it exists at a language specification level, but not in your code.
Your options are the conditional operator¹ (which is quite readable when you're used to it, but you've said you're looking for alternatives to it) or the if/else assigning to a in both parts:
let a;
if (3 === 4) {
a = 5;
} else {
a = 6;
}
Or you could use an inline function (IIFE):
let a = (() => { if (3 === 4} return 5 else return 6; })();
There is also a proposal being floated for "do expressions", which would look like this:
// Currently a proposal, not implemented in engines yet
let a = do { if (3 === 4) 5; else 6; };
That proposal is at Stage 1 of the process, so it may or may not progress, and if it progresses it could change markedly before doing so.
¹ Although you see "the ternary operator" a lot, the proper name is the conditional operator. It is a ternary operator (an operator accepting three operands), and currently JavaScript's only ternary operator, but that could change someday. :-)
Use ternary operator, because you can't assign if statement:
let a = 3 === 4 ? 5 : 6;
The reason this doesn't work is because if is, as you pointed out, a statement. An assignment requires an expression holding a value to be assigned. A statement doesn't (per se) have a value--it simply performs some side-effect instead.
What you can use if you want to assign a value conditionally is the ternary conditional operator, which is an expression:
let a = (3 === 4 ? 5 : 6)
At this point you're probably wondering, why does the console print a value if a statement merely performs side-effects? This is because statements have a completion value, which for an if statement is the completion value of the corresponding branch, and for an expression statement (which is what the 5 and 6 inside the blocks are), is whatever the expression evaluates to. This is mainly useful for when you want to evaluate an expression in the console and see what it produces, without having to issue a console.log() each time you do.
It's not returning anything. if is not an expression, it's a statement; it has no value.
The point of the ternary operator was to provide a more readable version of this:
let a;
if (condition) {
a = 1;
}
else {
a = 2;
}

Why is Boolean() so slow in Javascript?

According to the ECMAScript specification, both the unary logical NOT operator (!) and the Boolean() function use the internal function ToBoolean(), and the NOT operator also does a few checks to reverse the result. So why is a double logical NOT operation much faster than running the Boolean() function?
I used the following piece of code to test which was faster:
function logicalNotOperator() {
var start = performance.now();
for (var i = 0; i < 9999999; i++) !!Math.random();
return 0.001 * (performance.now() - start);
}
function booleanFunc() {
var start = performance.now();
for (var i = 0; i < 9999999; i++) Boolean(Math.random());
return 0.001 * (performance.now() - start);
}
var logicalNotOperatorResult = logicalNotOperator();
var booleanFuncResult = booleanFunc();
var diff = booleanFuncResult - logicalNotOperatorResult;
console.log('logicalNotOperator:', logicalNotOperatorResult);
console.log('booleanFunc:', booleanFuncResult);
console.log('diff:', diff);
Note: I am not referring to the new Boolean() constructor, but the Boolean() function that coerces the argument it's given to a boolean.
While Boolean will call the function (internally optimized), most JITs will inline the double not to use XOR which is far faster (source code reference - JägerMonkey).
And the JSperf: http://jsperf.com/bool-vs-doublenot
I don't know how Javascript JIT compiler executed internally. Also right now the Boolean function works faster in Chrome at 2020. But if there is some different browsers, different versions or different JS engines !! operator works faster I think I know the answer reason why. When you call a function there is extra work inside memory for push stack and pop stack. When you use ! (NOT operator) there is no need to create extra work inside memory for push/pop stack. That is why NOT operator works faster.

Why does (x += x += 1) evaluate differently in C and Javascript?

If the value of the variable x is initially 0, the expression x += x += 1 will evaluate to 2 in C, and to 1 in Javascript.
The semantics for C seems obvious to me: x += x += 1 is interpreted as x += (x += 1) which is, in turn, equivalent to
x += 1
x += x // where x is 1 at this point
What is the logic behind Javascript's interpretation? What specification enforces such behaviour? (It should be noted, by the way, that Java agrees with Javascript here).
Update:
It turns out the expression x += x += 1 has undefined behaviour according to the C standard (thanks ouah, John Bode, DarkDust, Drew Dormann), which seems to spoil the whole point of the question for some readers. The expression can be made standards-compliant by inserting an identity function into it as follows: x += id(x += 1). The same modification can be made to the Javascript code and the question still remains as stated. Presuming that the majority of the readers can understand the point behind "non-standards-compliant" formulation I'll keep it as it is more concise.
Update 2: It turns out that according to C99 the introduction of the identity function is probably not solving the ambiguity. In this case, dear reader, please regard the original question as pertaining to C++ rather than C99, where "+=" can be most probably now safely be regarded as an overloadable operator with a uniquely defined sequence of operations. That is, x += x += 1 is now equivalent to operator+=(x, operator+=(x, 1)). Sorry for the long road to standards-compliance.
x += x += 1; is undefined behavior in C.
The expression statement violates sequence points rules.
(C99, 6.5p2) "Between the previous and next sequence point an object shall have its stored value modified at most once by the evaluation of an expression."
JavaScript and Java have pretty much strict left-to-right evaluation rules for this expression. C does not (even in the version you provided that has the identity function intervening).
The ECMAScript spec I have (3rd Edition, which I'll admit is quite old – the current version can be found here: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf) says that compound assignment operators are evaluated like so:
11.13.2 Compound Assignment ( op= )
The production AssignmentExpression : LeftHandSideExpression # =
AssignmentExpression, where# represents one of the operators indicated
above, is evaluated as follows:
Evaluate LeftHandSideExpression.
Call GetValue(Result(1)).
Evaluate AssignmentExpression.
Call GetValue(Result(3)).
Apply operator # to Result(2) and Result(4).
Call PutValue(Result(1), Result(5)).
Return Result(5)
You note that Java has the same behavior as JavaScript – I think its spec is more readable, so I'll post some snippets here (http://java.sun.com/docs/books/jls/third_edition/html/expressions.html#15.7):
15.7 Evaluation Order
The Java programming language guarantees that the operands of
operators appear to be evaluated in a specific evaluation order,
namely, from left to right.
It is recommended that code not rely crucially on this specification.
Code is usually clearer when each expression contains at most one side
effect, as its outermost operation, and when code does not depend on
exactly which exception arises as a consequence of the left-to-right
evaluation of expressions.
15.7.1 Evaluate Left-Hand Operand First The left-hand operand of a binary operator appears to be fully evaluated before any part of the
right-hand operand is evaluated. For example, if the left-hand operand
contains an assignment to a variable and the right-hand operand
contains a reference to that same variable, then the value produced by
the reference will reflect the fact that the assignment occurred
first.
...
If the operator is a compound-assignment operator (§15.26.2), then
evaluation of the left-hand operand includes both remembering the
variable that the left-hand operand denotes and fetching and saving
that variable's value for use in the implied combining operation.
On the other hand, in the not-undefined-behavior example where you provide an intermediate identity function:
x += id(x += 1);
while it's not undefined behavior (since the function call provides a sequence point), it's still unspecified behavior whether the leftmost x is evaluated before the function call or after. So, while it's not 'anything goes' undefined behavior, the C compiler is still permitted to evaluate both x variables before calling the id() function, in which case the final value stored to the variable will be 1:
For example, if x == 0 to start, the evaluation could look like:
tmp = x; // tmp == 0
x = tmp + id( x = tmp + 1)
// x == 1 at this point
or it could evaluate it like so:
tmp = id( x = x + 1); // tmp == 1, x == 1
x = x + tmp;
// x == 2 at this point
Note that unspecified behavior is subtly different than undefined behavior, but it's still not desirable behavior.
In C, x += x += 1 is undefined behavior.
You can not count on any result happening consistently because it is undefined to try to update the same object twice between sequence points.
At least in C, this is undefined behavior. The expression x += x+= 1; has two sequence points: an implicit one right before the expression starts (that is: the previous sequence point), and then again at the ;. Between these two sequence points x is modified twice and this explicitly stated as undefined behavior by the C99 standard. The compiler is free to do anything it likes at this point, including making daemons fly out of your nose. If you're lucky, it simply does what you expect but there is simply no guarantee for that.
This is the same reason why x = x++ + x++; is undefined in C. See also the C-FAQ for more examples and explanations of this or the StackOverflow C++ FAQ entry Undefined Behavior and Sequence Points (AFAIK the C++ rules for this are the same as for C).
Several issues are at play here.
First and most important is this part of the C language specification:
6.5 Expressions
...
2 Between the previous and next sequence point an object shall have its stored value
modified at most once by the evaluation of an expression.72) Furthermore, the prior value
shall be read only to determine the value to be stored.73)
...
72) A floating-point status flag is not an object and can be set more than once within an expression.
73) This paragraph renders undefined statement expressions such as
i = ++i + 1;
a[i++] = i;
while allowing
i = i + 1;
a[i] = i;
Emphasis mine.
The expression x += 1 modifies x (side effect). The expression x += x += 1 modifies x twice without an intervening sequence point, and it's not reading the prior value only to determine the new value to be stored; hence, the behavior is undefined (meaning any result is equally correct). Now, why on Earth would that be an issue? After all, += is right-associative, and everything's evaluated left-to-right, right?
Wrong.
3 The grouping of operators and operands is indicated by the syntax.74) Except as specified
later (for the function-call (), &&, ||, ?:, and comma operators), the order of evaluation
of subexpressions and the order in which side effects take place are both unspecified.
...
74) The syntax specifies the precedence of operators in the evaluation of an expression, which is the same
as the order of the major subclauses of this subclause, highest precedence first. Thus, for example, the
expressions allowed as the operands of the binary + operator (6.5.6) are those expressions defined in
6.5.1 through 6.5.6. The exceptions are cast expressions (6.5.4) as operands of unary operators
(6.5.3), and an operand contained between any of the following pairs of operators: grouping
parentheses () (6.5.1), subscripting brackets [] (6.5.2.1), function-call parentheses () (6.5.2.2), and
the conditional operator ?: (6.5.15).
Emphasis mine.
In general, precedence and associativity do not affect order of evaluation or the order in which side effects are applied. Here's one possible evaluation sequence:
t0 = x + 1
t1 = x + t0
x = t1
x = t0
Oops. Not what we wanted.
Now, other languages such as Java and C# (and I'm assuming Javascript) do specify that operands are always evaluated left-to-right, so there's always a well-defined order of evaluation.
All JavaScript expressions are evaluated left to right.
The associativity of...
var x = 0;
x += x += 1
will be...
var x = 0;
x = (x + (x = (x + 1)))
So because of its left to right evaluation, the current value of x will be evaluated before any other operation takes place.
The result could be viewed like this...
var x = 0;
x = (0 + (x = (0 + 1)))
...which will clearly equal 1.
So...
var x = 0;
x = (x + (x = (x + 1)));
// x = (0 + (x = (0 + 1))); // 1
x = (x + (x = (x + 1)));
// x = (1 + (x = (1 + 1))); // 3
x = (x + (x = (x + 1)));
// x = (3 + (x = (3 + 1))); // 7

Why does javascript accept commas in if statements?

I stumbled across some javascript syntax that seemed like it should produce a parse error of some kind but doesn't:
if (true, true) {console.log('splendid')} else {console.log('horrid')} // splendid
if (true, false) {console.log('splendid')} else {console.log('horrid')} // horrid
It seems only the last expression affects the logic, though all expressions are executed:
if (console.log('super'), true) {console.log('splendid')} // super splendid
Anyone know why that is valid javascript syntax? Is there any practical use for it?
The comma operator chains multiple expressions together, and the result of the operation is the value of the last operand. The only real use for it is when you need multiple side effects to occur, such as assignment or function calls.
The comma operator evaluates each of its operands (from left to right)
and returns the value of the last operand.
https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Operators/Special_Operators/Comma_Operator
https://developer.mozilla.org/en/Core_JavaScript_1.5_Guide/Expressions_and_Operators#comma_operator
commas in javascript are actually pretty arcane. The coolest use I have seen is this
while(doSomething(), checkIfSomethingHappened());
the most common would be the way var is used in modern js
var foo = 1,
bar = 2;
This is also the same as in most other programming languages where you might have multiple iterators in a loop.
int x,y;
for(x = 0, y = 0; x < 10 || y < 100; x++, y++) {
....
}
I permits to do operations and comparisons in the same context.
Example:
if(a = 2, a > 1) console.log('a is', a)

Is not having local functions a micro optimisation?

Would moving the inner function outside of this one so that its not created everytime the function is called be a micro-optimisation?
In this particular case the doMoreStuff function is only used inside doStuff. Should I worry about having local functions like these?
function doStuff() {
var doMoreStuff = function(val) {
// do some stuff
}
// do something
for (var i = 0; i < list.length; i++) {
doMoreStuff(list[i]);
for (var j = 0; j < list[i].children.length; j++) {
doMoreStuff(list[i].children[j]);
}
}
// do some other stuff
}
An actaul example would be say :
function sendDataToServer(data) {
var callback = function(incoming) {
// handle incoming
}
ajaxCall("url", data, callback);
}
Not sure if this falls under the category "micro-optimization". I would say no.
But it depends on how often you call doStuff. If you call it often, then creating the function over and over again is just unnecessary and will definitely add overhead.
If you don't want to have the "helper function" in global scope but avoid recreating it, you can wrap it like so:
var doStuff = (function() {
var doMoreStuff = function(val) {
// do some stuff
}
return function() {
// do something
for (var i = 0; i < list.length; i++) {
doMoreStuff(list[i]);
}
// do some other stuff
}
}());
As the function which is returned is a closure, it has access to doMoreStuff. Note that the outer function is immediately executed ( (function(){...}()) ).
Or you create an object that holds references to the functions:
var stuff = {
doMoreStuff: function() {...},
doStuff: function() {...}
};
More information about encapsulation, object creation patterns and other concepts can be found in the book JavaScript Patterns.
For optimal speed with a nested function (function within internal scope of an outer function), I suspect you should use declarations, not expressions.
The question asks about "local functions" and optimization, but doesn't specify how the local functions are created. But it should, because the question's answer probably is different for the different techniques by which the "inner function" can be created.
Looking at the answer and test results by #cleong, I suspect that only his answer is using the optimal technique for function creation. There are three ways to create a function, and #cleong is showing us the one that provides fast execution. The three techniques are:
constructor
declaration
expression
Constructor isn't used much, it requires a string that has the text of the function body. This would be useful in reflective programming, where you do a "toString()" to get the function body, modify, then construct a new function. And that, of course, is more-or-less never done.
Declaration is used, but mostly for outer functions, not inner functions (by "inner function" I mean a function nested within another). Yet, based upon #cleong tests, it seems to be very fast; just as fast as an outer function.
Expressions are what everyone uses. This might not be the best idea; but it's what everyone does.
One major difference between function declarations and function expressions is that the declarations are subject to hoisting. Everyone knows that "var" declarations are hoisted; but so are "function" declarations. For things that are hoisted, computations are performed at compile time to determine the memory space that will be needed for the thing. Presumably, one would expect that the inner function is compiled at compile time, and can run much as would a compiled outer function.
I have a copy of Flannigan's "The Definitive Guide" book from about six years ago, and I remember reading the reverse of what I just wrote here. He said something like: expressions are compiled, and declarations are not. While he is the world's "definitive guide" to JavaScript, I have always suspected he might have gotten this one mixed up and backwards. I suspect that function inner declarations are more "ready to go" than are function expressions. The test results on this stackOverflow page seem to confirm my long held suspicions.
Looking at the #cleong test results, it just seems that declaration, not expression, is the way to go for inner functions, if optimal execution speed is a concern.
The original question was asked in 2011. Given the rise of Node.js since then, I thought it's worth revisiting the issue. In a server environment, a few milliseconds here and there can matter a lot. It could be difference between remaining responsive under load or not.
While inner functions are nice conceptually, they can pose problems for the JavaScript engine's code optimizer. The following example illustrate this:
function a1(n) {
return n + 2;
}
function a2(n) {
return 2 - n;
}
function a() {
var k = 5;
for (var i = 0; i < 100000000; i++) {
k = a1(k) + a2(k);
}
return k;
}
function b() {
function b1(n) {
return n + 2;
}
function b2(n) {
return 2 - n;
}
var k = 5;
for (var i = 0; i < 100000000; i++) {
k = b1(k) + b2(k);
}
return k;
}
function measure(label, fn) {
var s = new Date();
var r = fn();
var e = new Date();
console.log(label, e - s);
}
for (var i = 0; i < 4; i++) {
measure('A', a);
measure('B', b);
}
The command for running the code:
node --trace_deopt test.js
The output:
[deoptimize global object # 0x2431b35106e9]
A 128
B 130
A 132
[deoptimizing (DEOPT eager): begin 0x3ee3d709a821 b (opt #5) #4, FP to SP delta: 72]
translating b => node=36, height=32
0x7fffb88a9960: [top + 64] <- 0x2431b3504121 ; rdi 0x2431b3504121 <undefined>
0x7fffb88a9958: [top + 56] <- 0x17210dea8376 ; caller's pc
0x7fffb88a9950: [top + 48] <- 0x7fffb88a9998 ; caller's fp
0x7fffb88a9948: [top + 40] <- 0x3ee3d709a709; context
0x7fffb88a9940: [top + 32] <- 0x3ee3d709a821; function
0x7fffb88a9938: [top + 24] <- 0x3ee3d70efa71 ; rcx 0x3ee3d70efa71 <JS Function b1 (SharedFunctionInfo 0x361602434ae1)>
0x7fffb88a9930: [top + 16] <- 0x3ee3d70efab9 ; rdx 0x3ee3d70efab9 <JS Function b2 (SharedFunctionInfo 0x361602434b71)>
0x7fffb88a9928: [top + 8] <- 5 ; rbx (smi)
0x7fffb88a9920: [top + 0] <- 0 ; rax (smi)
[deoptimizing (eager): end 0x3ee3d709a821 b #4 => node=36, pc=0x17210dec9129, state=NO_REGISTERS, alignment=no padding, took 0.203 ms]
[removing optimized code for: b]
B 1000
A 125
B 1032
A 132
B 1033
As you can see, function A and B ran at the same speed initially. Then for some reason a deoptimization event occurred. From then on B is nearly an order of magnitude slower.
If you're writing code where performance is importantly, it's best to avoid inner functions.
It completely depends on how often the function is called. If it's a OnUpdate function that is called 10 times per second it is a decent optimalisation. If it's called three times per page, it is a micro optimalisation.
Though handy, nested function definitions are never needed (they can be replaced by extra arguments for the function).
Example with nested function:
function somefunc() {
var localvar = 5
var otherfunc = function() {
alert(localvar);
}
otherfunc();
}
Same thing, now with argument instead:
function otherfunc(localvar) {
alert(localvar);
}
function somefunc() {
var localvar = 5
otherfunc(localvar);
}
It is absolutely a micro-optimization. The whole reason for having functions in the first place is so that you make your code cleaner, more maintainable and more readable. Functions add a semantic boundary to sections of code. Each function should only do one thing, and it should do it cleanly. So if you find your functions performing multiple things at the same time, you've got a candidate for refactoring it into multiple routines.
Only optimize when you've got something working that's too slow (If it's not working yet, it's too early to optimize. Period). Remember, nobody ever paid extra for a program that was faster than their needs/requirements...
Edit: Considering that the program isn't finished yet, it's also a premature optimization. Why is that bad? Well, first you're spending time working on something that may not matter in the long run. Second, you don't have a baseline to see if your optimizations improved anything in a realistic sense. Third, you're reducing maintainability and readability before you've even got it running, so it'll be harder to get running than if you went with clean concise code. Fourth, you don't know if you'll need doMoreStuff somewhere else in the program until you've finished it and understand all your needs (perhaps a longshot depending on the exact details, but not outside the realm of possibility).
There's a reason that Donnald Knuth said Premature optimization is the root of all evil...
A quick "benchmark" run on an average PC (i know there are lots of unaccounted-for variables, so dont comment on the obvious, but it's interesting in any case):
count = 0;
t1 = +new Date();
while(count < 1000000) {
p = function(){};
++count;
}
t2 = +new Date();
console.log(t2-t1); // milliseconds
It could be optimised by moving the increment to the condition for example (brings running time down by about 100 milliseconds, although it doesn't affect the difference between with and without function creation, so it isn't really relevant)
Running 3 times gave:
913
878
890
Then comment out the function creation line, 3 runs gave:
462
458
464
So purely on 1000,000 empty function creations you add about half a second. Even assuming your original code is running 10 times a second on a handheld device (let's say that devices overall performance is 1/100 of this laptop, which is exaggerated - it's probably closer to 1/10, although will provide a nice upper bound), that's equivalent to 1000 function creations/sec on this computer, which happens in 1/2000 of a second. So every second the handheld device is adding overhead of 1/2000 second of processing... half a millisecond every second isn't very much.
From this primitive test I would conclude that on a PC this is definitely a micro-optimisation, and if you're developing for weaker devices, it is almost certainly as well.

Categories