Reputation: 3929
At a job interview, I was perplexed to hear "javascript can evaluate statements out of order." To what degree is this true? I can imagine a hundred ways to explicitly evaluate statements out of order -- such as in a time-sharing operating system. But he seemed to say that if I evaluate
console.log('a')
console.log('b')
that the Javascript spec somehow doesn't require that the output would be a
first then b
. I can imagine that the evaluator might try to evaluate the second statement if the IO of the first is blocking if the statements are functionally pure, i.e. no side effects, but side effects must always occur in sequence, correct? And of course IO is one big side effect.
To what extent can spec-compliant Javascript evaluate out of order? Or was this a case of miscommunication?
Upvotes: 5
Views: 485
Reputation: 324650
For the most part, yes. With two major exceptions (leaving aside the obvious "define a function, call the function" which effectively "goes back" to the function body):
1: Hoisting. var
statements are hoisted, so if you write
alert(a);
var a = 123;
You get undefined
, and not an error message. This is because it is hoisted to
var a;
alert(a);
a = 123;
Similarly, function definitions are hoisted too. If you write:
foo(123);
function foo(num) {alert(num);}
It will work, because the function is hoisted. However, this does NOT work if you wrote
foo(123);
foo = function(num) {alert(num);}
Because that's an assignment of an anonymous function, not a function definition.
2: Asynchronous functions.
A common mistake among beginners is to write this:
var a = new XMLHttpRequest();
a.open("GET","sompage.php",true);
a.onreadystatechange = function() {
if( a.readyState == 4 && a.status == 200) {
myvar = "Done!";
}
};
a.send();
alert(myvar);
They expect the alert to say Done!
, but instead they get an inexplicable error about it not being defined. This is because the myvar = "Done!"
hasn't been run yet, despite appearing earlier in the script.
See also this anecdote from Computer Stupidities:
An introductory programming student once asked me to look at his program and figure out why it was always churning out zeroes as the result of a simple computation. I looked at the program, and it was pretty obvious:
begin readln("Number of Apples", apples); readln("Number of Carrots", carrots); readln("Price for 1 Apple", a_price); readln("Price for 1 Carrot", c_price); writeln("Total for Apples", a_total); writeln("Total for Carrots", c_total); writeln("Total", total); total := a_total + c_total; a_total := apples * a_price; c_total := carrots + c_price; end;
- Me: "Well, your program can't print correct results before they're computed."
- Him: "Huh? It's logical what the right solution is, and the computer should reorder the instructions the right way."
Upvotes: 1
Reputation: 3406
Clearly miscommunication.
The dude was maybe referring to JavaScript hoisting. You can read more about it here : http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
Furthermore, you can learn more particularities of the language here: http://bonsaiden.github.com/JavaScript-Garden/
Upvotes: 2
Reputation: 340763
JavaScript is single threaded (web workers aside). Period. ECMA-262 Language Specification Edition 5.1 says nothing about out-of-order execution. In your simple example these two statements are guaranteed to be executed in the same order.
Moreover, single block of JavaScript code will never be interrupted by any other block of code, e.g. event handler. That's why long running blocks of code cause UI to freeze:
for(var i = 0; i < 1000000000; ++i) {
console.log(i);
}
It's guaranteed that the block of code above will never be interrupted or reordered. As long as the loop is running, all event handlers and timeouts wait for single thread. And of course, numbers will appear in correct order.
What might be executed out-of-order is an asynchronous timeout:
setTimeout(function() {
console.log('a');
}, 1);
setTimeout(function() {
console.log('b');
}, 1);
Here you might expect a
to be printed first, but it's possible that JS engine will reorder these events. After all you schedule these calls to execute at almost the same point in time.
Upvotes: 8
Reputation: 49929
I think they tried to put you on your wrong foot. Javascript is sequensial. Otherwise functions where you calculate values won't work out. What can be true is that console.log
activates an Async task
which means it can be executed in a different order. Like an Ajax
call, a Webworker
, a timeout
or an interval
.
If you do the following it will result B than A, this is not a sequensial code because in code. A comes for B but B is executed first.
setTimeout(function(){
console.log("A")
}, 5);
console.log("B");
Upvotes: 0