I last talked about unknown values and how they work in expressions, but what happens when an unknown value is passed to a conditional statement? Let's say you try to do:
var x = new Date();
if (x < new Date(2013, 3, 12)) {
console.log('It is before April 12th, 2013');
} else {
console.log('It is on or after April 12th, 2013');
}
What should happen here? From an analysis perspective, both branches will be run at some point in time by someone, so it makes sense to analyze both branches and this is exactly what the code processor does. In general, anytime a decision needs to be made on whether or not a block of code needs to be executed and that decision is based on an unknown value, that code is executed.
This raises the question of course, what happens when statements inside of this code block affect code outside of the block? For example:
var x = 10;
if (new Date()) {
x += 10;
}
console.log(x);
What should the value of x be when it is logged to the console? Since it depends on how the actual code will be executed on device, the answer is that we don't know and so I set x to unknown. Since code processor has to treat assignments (and related operations) differently inside of the block than it does outside of the block, the code processor flags the block as ambiguous.
There are further rules and restrictions when dealing with these ambiguous blocks. What happens when a return statement is encountered inside of an ambiguous block? In this case, the code processor marks the function as having an unknown return value, stops evaluating the block, and continues outside the block. Semantically, the return behaves as if it were a break statement inside a loop block. The rest of the function is evaluated, and then unknown is returned. Similar, but a lot more tricky, is throw statements; honestly I haven't figured this one out yet.
My examples so far have all been if statements, but what about loops? The same rules apply, with special handling of the iteration constructs. For for loops, while loops, and do-while loops, if the loop conditional is unknown, the body of the loop is evaluated exactly once as an ambiguous block. If the iteration condition is known for the first few iterations, but later becomes unknown, then the block is evaluated one more time in ambiguous mode as a sort of "clean up." Note that a for loop conditional is the middle argument, i.e. the "i < Date.now()" bit below:
for (var i = 0, i < Date.now(); i++) {}
For-in loops are different than the other loops, since they don't have an iteration condition. Instead, a for-in loop is evaluated in ambiguous mode if the value to be iterated over is unknown, as shown below:
for (var i in Date.now()) {}
There is one more important case that the code processor handles: what happens when a function is called inside of an ambiguous block? That will be discussed in my next post dealing with ambiguous contexts, so stay tuned.