I ran into this piece of code:
<a ng-click= "item.statusId !== itemStatus.in || transfer()">
I guess we can generalize as:
<element ng-click = "someVar !== someValue || doStuff()">
I then found this article on short circuits and another more focused one once I knew what they are called. However, I still don't get it.
Does it basically work on the principle of an OR statement ending evaluation if the first statement evaluates to true? So if the first statement is true, end evaluation, if it's false, run the function in the second half of the OR statement? (This is the main question I am asking, everything else is extra).
I guess that part I don't get is whether the compiler interprets this code differently or it still evaluates to false and just runs the function. Not even sure how to phrase Q.
Does it basically work on the principle of an OR statement ending evaluation if the first statement evaluates to true? So if the first statement is true, end evaluation, if it's false, run the function in the second half of the OR statement?
It's effectively shorthand for an if statement, and you intuited correctly why it works. For more details on short-circuit evaluation in JavaScript, see this Stack Overflow question.
That code is equivalent to:
//Note the intentional and explicit use of `== false` to mean falsy (NOT `=== false` to indicate strict equality test for false)
if( (item.statusId !== itemStatus.in) == false ) {
transfer();
}
It is an interesting means of executing a function only when a condition is falsy.
There are many different examples of this around on StackOverflow, and is not specific to AngularJS.
Related
Does an "if" statement with multiple "or" operators exit when the first condition returns true, or are all conditions evaluated?
i.e. does the order of your conditions matter?
Example scenario:
A shouldComponentUpdate() function with an if statement and the evaluated conditions vary in cost.
Does the order of the conditions (with the least expensive first) promise an improvement in performance or will the entire if statement get evaluated even if the first condition will return a true?
For example:
Assume an if statement in the form:
if ( (this.props.value != nextProps.value) || (deepDiffer(object1, object2) )
If (this.props.value != nextProps.value) returns true, will the code still evaluate the deepDiffer? Or will it immediately enter the if statement and execute the conditional code?
This is Javascript, so yes, it exits when the first condition is true.
According to MDN:
As logical expressions are evaluated left to right, they are tested
for possible "short-circuit" evaluation using the following rules:
false && anything is short-circuit evaluated to false.
true || anything is short-circuit evaluated to true.
The rules of logic guarantee that these evaluations are always correct. Note that the anything part of the above expressions is not evaluated, so any side
effects of doing so do not take effect.
In a condition, if there are multiple 'or', they are checked from left to right and if the first is true, it won't check the nexts.
Same behaviour in a 'and' chain, when the first false is encounter, the nexts won't be checked
This is basic Javascript
I am currently having a hard time figuring out how to use multiple conditions for my if-else statements. I can do 1 condition at a time, but multiples are a problem for me. I'm not quite sure where to start with the multiple one as I'm using the HTML form stuff, and I'm not sure where to start with it as well. Any sample code is fine as I would like to learn rather than have people figure everything out for me.
Ok, let's start from the beginning.
You agree that this code right here:
if (true)
console.log('foo');
obviously prints out 'foo' on your console, cause the condition is satisfied (i.e. is true).
Let's try something different now:
if (true && false)
console.log('bar');
The && in Javascript and most programming languages is the and operator, which evaluates to true only if both the conditions at its left and at its right are true. This means that the code above does not print out 'bar'.
if (true || false)
console.log('bla');
The || operator, on the other hand, is the or operator, which is true when one of the two conditions (or both) is true. In this case, 'bla' is printed out on your console.
In the end, let's have a look at the ! operator (not): if the condition that follows the operator is true, then it evaluates to false, and viceversa. So writing if (!false) equals if (true).
Now you can apply these simple rules to easily use multiple logical conditions in one if or else branch. Remember the precedence of the logical operators, i.e. which one you have to evaluate first if you have more than one, taking a look here: Which Logic Operator Takes Precedence
I've starting to dig my teeth into backbone and when working with a router function creating and destroying views I came across this little snippet, which didn't quite make sense to me as I've always assumed these sorts of operators only work in conditional statements,
this.view && this.view.remove();
It was inside of a method attached to the router which seems to work like a charm, but I'm always weary of voodoo code that doesn't sit well with me.
Heres the full method
loadView : function(view) {
this.view && this.view.remove();
this.view = view;
}
Would love to understand this a bit better, hope its not too silly to ask.
Cheers.
In JavaScript:
this.view && this.view.remove();
is equivalent to
this.view ? this.view.remove() : this.view;
The righthand side is only executed if the lefthand side is truthy. If the value of the expression is ignored and the lefthand side has no side-effects (as in this case), then it's also equivalent to this:
if (this.view) {
this.view.remove();
}
So, in this specific case if there is an existing view, then it is removed. Note that the value of this expression is not necessarily a boolean (unlike in many other languages); it's whatever is returned by remove. However, this value is ignored, so it's not actually pertinent.
The operator && in javascript evaluates the first expression, if it is falsy it is returned, if it is truthy the second expression is evaluated and returned.
For || it is the other way round: the first expression is evaluated, if it is truthy it is returned, else the second expression is evaluated and returned.
I opened a js file that I wrote a while back and although it's working, I thought I spotted an error. (JS is not my primary language)
I had this:
if( myvar = fieldval.match(mypattern))
{
//Do Stuff
}
So I think I get it. Is this a correct statement?:
A javascript assignment operation evaluates to the value being assigned.
I tested on w3schools
<script type="text/javascript">
var str="The rain in SPAIN stays mainly in the plain";
var patt1=/ain/gi;
var test
document.write(test=str.match(patt1));
</script>
and it writes "ain,AIN,ain,ain" where I might have expected it to write "true" or not to write at all because boolean true is not a string. Is my line of thought and then ultimate conclusion correct. (I ask about my line of thought on this because I do not have a lot of formal CS training.)
It is a correct statement. The new value of myvar is tested:
if ( myvar = fieldval.match(mypattern) )
When the String.match method cannot find a match, it returns null. !!null === false, so the if-block is not evaluated. When any non-empty match is found, the condition is true, and the block is evaluated.
In this case, it is very likely that the if-statement is correct, and that the following is intended:
if ( (myvar = fieldval.match(mypattern)) !== null )
Rob W is correct, however it's extremely poor practice to put an assignment in an if statement like that. In the future, anyone coming along (including yourself) will scratch their head at that statement to determine if that's what you really meant.
I highly recommend Douglas Crockford's talk: http://www.youtube.com/watch?v=taaEzHI9xyY It'll make anyone (Js dev or not) a better developer for watching it because you'll consider the implications of your coding style and what future maintainers might assume.
match returns an array of matching values, not boolean. Use test instead.
The function string.match() returns an array of matches, or null if no matches are found. The code works because null evaluates to false in an if statement, while an array evaluates to true.
So indeed, the result of str.match is stored in myvar and then myvar is evaluated as boolean. It works as expected.
I was exploring the Google Closure Compiler, and one thing I noticed was that it converts while(true) into for(;;).
Both do hang the browser, but why does the empty for loop not break out of itself immediately? The second part of it is empty, and therefore falsy. Isn't it true that when the second part is falsy, the for loop stops and execution continues with code which comes after the for loop?
Could someone perhaps give an explanation for this?
No, it is not true.
See: https://developer.mozilla.org/en/JavaScript/Reference/Statements/for
condition
An expression to be evaluated before each loop iteration. If this
expression evaluates to true,
statement is executed. This
conditional test is optional. If
omitted, the condition always
evaluates to true. If the expression
evaluates to false, execution skips to
the first expression following the for
construct.
I should perhaps give a link to ECMAScript reference, but I'm pretty sure it states more or less same thing.
From the ECMAScript language specification:
IterationStatement : for (ExpressionNoIn_opt ; Expression_opt ; Expression_opt) Statement
If the first Expression is present, then
Let testExprRef be the result of evaluating the first Expression.
If GetValue(testExprRef) is false, return (normal, V, empty).
Since the first expression (the second argument to for) is not present, this section is never run, so the for loop does not exit.
An empty middle part should be interpreted as true, so it's not falsy. It has the same semantics in C and other languages with that kind of loop (like C#, Java and so on). It would be a real trap to have changed it for JavaScript.
There is evaluation algorothm of for loop in Standard ECMA-262 script that says there are only two situations in which loop will end:
break statement
value of middle statement equal to false, but only if this statement is present, so it doesnt have to be necessary valuated as true (probably in mozilla js engine it is).