Javascript conditional order evaluation - javascript

Can I count on Javascript failing immediately when one condition in an expression results to false?
f = {'a':'b'};
if (f.a !== undefined || f.a === 'b') {
// Is this OK to use, because the second condition will never be evaluated?
}

Yes, this is known as short circuit evaluation.
With an AND logical operator, if the first evaluates to false, then the second is never evaluated, because the condition knows enough already to be met.
With the OR logical operator, if the first one is false, it will evaluate the second one. Otherwise if the first is true it won't evaluate the second (no need to).
This is also why you see...
var a = function(b) {
b = b || 7;
}

Related

Why does JavaScript's logical AND (&&) not work the same as an if conditional?

I've been doing JS development for a long time now, and for years I thought I could short circuit a conditional statement using the logical AND. In fact, I do this ALL THE TIME in my React components with conditional rendering. But it turns out it doesn't work the way I would expect all the time. The question is, why?
Here is an example for Node 8.15.0:
> a = 0.0
0
> a && console.log(a)
0
> if(a) console.log(a)
undefined
> !!a && console.log(a)
false
Specifically, why does a && console.log(a) not work the same as if (a) console.log(a)
if(a) ... is a statement. a && ... is an expression.
This behaviour is specific to a console. If a line evaluates to an expression, the result outputted, otherwise it's considered that a line was evaluated to undefined.
a && ... is a short-circuit. This means that if a is falsy, the expression evaluates to a. If a is truthy, the expression is evaluated to ....
This doesn't affect the way both are used in real application instead of a console. If the result of the evaluation isn't used, both if and short-circuit evalution act the same way, i.e. evaluate ... only if a condition is truthy.
!! operator convert variable to boolean.
In your case a equal to 0 so it will convert it to false, and because of this you see false as output for !!a && console.log(a)
The first expression outputs 1 line to the console, which is what the statement evaluates to:
a && console.log(a)
0
The expression clearly evaluates to the value of a. That's because this short circuit evaluation can be considered equivalent to the following conditional ternary:
a ? console.log(a) : a
The second expression evaluates to undefined because it is not an actual expression but a block construct. With braces this time:
if (a) { console.log(a) }
undefined
The third expression is quite similar to the first one, except that this time not the value of a is returned but the value of the sub-expression !!a, or false:
!!a && console.log(a)
false
Note If a would be a truthy value both the first and third statements would evaluate to undefined, the return value of console.log.

What does an exclamation mark before a variable mean in JavaScript

I'm trying to learn JavaScript by going through some code in an application and I keep seeing !variable in if conditions. For example:
if (!variable.onsubmit || (variable.onsubmit() != false)) {
What is it? Some kind of test if the variable is empty?
! is the logical not operator in JavaScript.
Formally
!expression is read as:
Take expression and evaluate it. In your case that's variable.onsubmit
Case the result of that evaluation and convert it to a boolean. In your case since onsubmit is likely a function, it means - if the function is null or undefined - return false, otherwise return true.
If that evaluation is true, return false. Otherwise return true.
In your case
In your case !variable.onsubmit means return true if there isn't a function defined (and thus is falsy), otherwise return false (since there is a function defined).
Simply put - !variable means take the truth value of variable and negate it.
Thus, if (!variable) { will enter the if clause if variable is false (or coerces to false)
In total
if (!variable.onsubmit || (variable.onsubmit() != false)) {
Means - check if variable.onsubmit is defined and truthy (thus true), then it checks if calling onsubmit returns a result that coerces to true. In a short line it checks if there is no onsubmit or it returns true.
Next time, how do I find this myself?
MDN has a list of operators here.
The language specification specifies such operators, though being the official specification it does contain some jargon which might be hard to understand.
It is a negation operator used for truth tests on a variable.
var myVariable = 1;
if ( ! myVariable )
{
// myVariable evaluates as false
}
if ( myVariable )
{
// myVariable evaluates as true
}
The selected answer already answers the question. One thing to add in this is that ! operator can be used in a rather interesting fashion.
obj = {}
if (!!obj) {console.log('works')} // !!obj = true
obj = undefined
if (!!obj) {console.log('does not work')} // !!obj = false
So double !! will change any expression to a boolean value with no exceptions.
This has a very peculiar use case in some cases.
Lets say there is a function that returns either true or false and nothing else. In that case one could just change return returnValue to return !!returnValue for extra caution (although not need in most of the cases)
Conversely, if a function only accepts true or false and nothing else, one could just call the function as functionA(!!parameter) instead of functionA(parameter), which again is not needed in most of the cases, but could ensure extra security
! is a logic reversal operator, if something was true it will change it to false, if something is false, it will change to true.
example, we know that empty string or 0 in boolean is false.
let a = Boolean("")
console.log(a) // shows false, because empty string in boolean is false
console.log(!a) // shows true, because logic is reversed
easier example:
let a = 5
let b = 1
let c = a > b
console.log(c) // shows true, since a,5 is bigger than b,1
console.log(!c) // shows false, since logic is now reversed

Javascript && operator - clarification? [duplicate]

This question already has answers here:
Why don't logical operators (&& and ||) always return a boolean result?
(9 answers)
Closed 8 years ago.
edit :
Quote removed. is not related to the question.
Question
How come does it always (when all are truthy) takes the last value ?
Examples :
f= 1 && 2 && 3 //3
f= 'k' && 'd' && 's' //'s'
p.s. : I've noticed that when investigating the pub/sub using $.callbacks
Operator && acts as an if-statement. The short-circuit occurs only if a value is false. Otherwise, it keeps evaluating statements.
When you write a && b it means: a ? b : a.
Similarly, a || b means: a ? a : b.
Edit: author has clarified the question significantly.
JavaScript logical AND operator return the left operand if it is falsy or else it returns the right operand.
Let us take a look at the table of logical truth:
A B A && B
true true true
true false false
false true false
false false false
As you can see, if A is false, we can return it:
A A && B
false false
false false
If A is not false, we can return B:
B A && B
true true
false false
This is a minor optimization, which leads to interesting sideeffects when used with weak typing, such as inline if:
var result = callback && callback()
// Generally equivalent to a simple if:
if (callback)
result = callback();
else
result = null;
Also using default options:
name = name || 'John';
// Generally equivalent to a simple if:
if (!name)
name = 'John';
As to why it happens, well, because these operators are defined like that in ECMA-262.
So how come does it always (when all are truthy) takes the last value ?
Because it can't short-circuit if the leading values are truthy, because it's an "AND" operator, and all operands must be truthy to satisfy the condition.
Re your comment below:
yes but why does it returns the last value ?
Because it's useful. :-) In the very first version of JavaScript from Netscape, it just returned true if the overall expression was true and false if not, but almost immediately they realized that it's much more useful if it returns the final operand.
For instance, you can do this:
var value = obj && obj.value;
...which will set value to be either a falsey value (if obj is falsey) or obj.value (if obj is not falsey). Importantly, it won't throw an error if obj is falsey. Very handy for guarding if you don't know for sure that obj is set. You don't have to stop at one level, either:
var value = obj && obj.sub && obj.sub.value;
value will either be falsey, or the value of obj.sub.value if both obj and obj.sub are truthy (e.g., because we seem to be using them as objects, they're object instances rather than null or undefined).
|| does the same sort of thing: It returns its first truthy operand.
More: JavaScript's Curiously Powerful OR Operator (||)
Because if first one is truthy, then it should go on and check second operand till the last one. If you would go with 1 || 2 || 3 instead it will return 1.
&& is a logical operator. This tests whether a value is truthy or falsy. This linked article explains that falsy values are equal to undefined, null, NaN, 0, "" and false.
Logical expressions are checked from left to right. If any part of the expression is evaluated t be falsy, the remainder of the expression will not be evaluated. In your examples, the value is always truthy. Here we can break down your first expression:
f = 1 && 2 && 3;
f = 1 /* Okay, 1 is a truthy value, lets continue... */
f = 2 /* Still truthy, let's continue... */
f = 3 /* Still truthy, we've reached the end of the expression, f = 3. */
If any of the values before 3 were falsy, the expression would have ended. To show this in action, simply redeclare your variable as:
f = 1 && 2 && 0 && 3;
Here 0 is a falsy value (as mentioned above). The execution of your expression here will end at 0:
f = 1 /* Okay, 1 is a truthy value, lets continue... */
f = 2 /* Still truthy, let's continue... */
f = 0 /* Hey, this is falsy, lets stop here, f = 0. */
f = 3 /* We never get here as the expression has ended */
Here f ends up being 0.
In your jQuery.Topic() example, && is used to ensure that id actually exists:
topic = id && topics[id]
We can break this down in the same way:
/* Assume this is your topics array: */
topics = ["", "My First Topic", "My Second Topic"];
/* If we pass in the value 1 as "jQuery.Topic(1)": */
topic = id && topics[id]
topic = 1 /* This is truthy, let's continue... */
topic = topics[1] /* topics[1] === "My First Topic" */
/* Now lets assume we pass in nothing as "jQuery.Topic()": */
topic = id && topics[id]
topic = null /* This is falsy, let's stop here, topic = null. */
The following if statement will only work if topic is truthy. In the first example, this is the case as topic has a value which is set to a string which isn't empty. In the second example, topic is null which is falsy.
The ECMAScript Standard states 12.11.2 Runtime Semantics: Evaluation:
LogicalANDExpression : LogicalANDExpression && BitwiseORExpression
1. Let lref be the result of evaluating LogicalANDExpression.
2. Let lval be GetValue(lref).
3. Let lbool be ToBoolean(lval).
4. ReturnIfAbrupt(lbool).
5. If lbool is false, return lval.
6. Let rref be the result of evaluating BitwiseORExpression.
7. Return GetValue(rref).
That is, first we check whether the first operand is evaluated to be a "falsy" value (null, false, 0). If it is, then the first operand is returned.
If, however, it's "thruthy", then the same process is repeated for the second operand and if it is evaluated as a truthy value, then the original value is returned (7. Return GetValue(rref)).
Short-circuit evaluation and returning the second expression instead of a bool are quite useful features.
The && operator evaluates the left operand and if it's truthy evaluates the right operand. Similarly the || operator evaluates the left operand and if it's falsy evaluates the right operand.
This allows to write things like
draw_element(color || "#F00");
with the meaning of using color unless if it's not specified (e.g. color is null, undefined or "") and in that case the default value is used.
You can even use things like
draw_element(color || pick_new_color());
and the function pick_new_color() will be called only if a color is not specified.
A very common use of && instead is to avoid errors, e.g:
if (x && x.constructor == Array) {
...
}
because if x is null or undefined you cannot access attributes (an exception would be raised if you try). The fact that && returns the first result if it's falsy instead of just false is not so useful indeed. Your code example does it, but it's not something you will find often in Javascript programs.
To recap: && and || are short-circuiting (i.e. they don't even evaluate the second operand if the result is known after evaluating the first) and this is very useful. They also return the falsy/truthy value itself instead of a bool, and this is very useful for || (not so much useful for &&).

Logical operator && and two strings in javascript

When I use the logical operator && between two strings, why does it give me the second string as output:
console.log("" && "Dog"); // ""
console.log("Cat" && "Dog"); // "Dog"
I realize that the with the exception of 0, false, null, undefined, "" and NaN, everything else is evaluated as a boolean true in a logical expression like the one above. But why is the output the second string and not the first? And why is the ouput not just "true" since it is being evaluated as a boolean expression?
in the expression
"Cat" && "Dog"
// => "Dog"
Because you're using &&, JavaScript is promising you that it will verify that both sides of the expression are true. In this case, "Dog" is the just the last evaluated thing.
To be more explicit, you could do something like
var c = "Cat" != null && "Dog" != null
It's a little bit more wordy, but this boils down to
var c = true && true
console.log(c)
// => true
If you want a simple shortcut for the boolean, use the Boolean constructor -
var c = Boolean("Cat" && "Dog")
console.log(c)
// => true
If you just use a simple REPL or JavaScript console, you'd be able to see this output very easily.
Per one of the comments below
Using ||, JavaScript is promising you that at least one of the sides is true. Since "Cat" is true, it stops there and returns "Cat". This is known as Short-circuit evaluation
I think this is because of nature of logical operator &&. Javascript executes expression "cat" && "Dog" in following way:
Checks the value "cat" - it returns something else than "", 0, null, undefined or false and is truthy. Javascript sees && and so it continues expression and faces string "Dog", which is something else than "", 0, null, undefined or false and is truthy, expression ends and expression returns the last value it checked.
If you replace && with || expressions ends at first truthy value and thats way
var boolean = "cat" || "dog"
returns first value: cat
Answer by #naomik pretty much covers it. If you want to go deep, I suggest taking a look at the ECMAScript specification, section 11.11:
http://www.ecma-international.org/ecma-262/5.1/#sec-11.11
In the "Semantics" section, we can see:
The production LogicalANDExpression : LogicalANDExpression &&
BitwiseORExpression is evaluated as follows:
Let lref be the result of evaluating LogicalANDExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is false, return lval.
Let rref be the result of evaluating BitwiseORExpression.
Return GetValue(rref).
Because of the way logic works, if you need to test if both items are true, and you already know the first item is true, then the test totally depends on the second item.
true && someValue is equivalent to just someValue
For this reason, the operator && can be handled by returning its operands instead of true/false values, and just testing the first operand and not the second
a && b:
if a evaluates to false, no need to test further, return a (as it's false)
else if a evaluates to true, the result totally depends on b, so just return b (no need to test if b evaluates to true or false, just return it)
In code this is like
function and(a,b) {
if(!a) return a;
return b;
}
Similarly operator || can be defined as
function or(a,b) {
if(a) return a;
return b;
}
Returning operands instead of true/false has a few advantages:
requires less evaluations (notice b is never evaluated, in both cases)
does not require a definition of true/false so it works more broadly, even cross language or if the value of "true" changes
can be "hacked" to be used, without an if, to do stuff like string1 && string2 that has a useful meaning: "if string1 is not empty use string2 otherwise keep it empty (to replace every word of a string with the text "word": aString.split(" ").map(function(word) {return word && "word"});
JavaScripters love that kind of stuff (exploiting one operator side effect out of the usual context to get a different, unexpected behaviour), they do this to show off language knowlodge at parties. :D

What kind of Javascript notation / shortcut is this? [duplicate]

This question already has answers here:
Javascript || operator
(5 answers)
Closed 9 years ago.
Came across the following on someone's site and I'm curious to understand the shortcut applied here. I simplified the variables for demo purposes.
function(){
_imaboolean || ($element.removeClass("hidden").addClass("visible"), this.imaboolean = !0)
}
Same thing with
this._imaboolean && ($element.removeClass("visible").addClass("hidden"), this._imaboolean = !1)
That is some awful "clever" code, however, let's decompose it!
_imaboolean || ($element.removeClass("hidden").addClass("visible"), this.imaboolean = !0)
First, let's replace all the expressions with placeholders (note these expressions are not pure and have side-effects):
a || (b, c)
Note that || is short-circuiting such that the right expression - (b, c) - will only be evaluated if a evaluates to a false-y value.
So, let's assume that a evaluates to a false-y value, then (b, c) is evaluated. In this case the , operator separates sub-expressions; all the sub-expressions are evaluated in order. The result of the expression is the result of the last sub-expression.
This means it is roughly equivalent to (although there is no function or binding context and the result is thrown out anyway):
(function () { b; return c })()
Did that make sense? No, of course not!
Write it like you mean it:
if (!_imaboolean) {
$element.removeClass("hidden").addClass("visible");
this.imaboolean = true; // get rid of !0 too
}
This code can be inflated to:
function() {
if (!this.imaboolean) {
$element.removeClass("hidden").addClass("visible");
this.imaboolean = true;
}
}
The || is used as a short circuit, if imaboolean is true it will break out, however if it's false it will execute the remaining portion of the expression. !0 is a minified way of saying true (because 0 evaluates to false in a boolean expression).
I believe it is short for
function(){
if( ! _imaboolean){
$element.removeClass("hidden").addClass("visible");
this.imaboolean = true;
}
}
Its also generally terrible coding in my opinion and should not be copied.
It's a short-circuit evaluation where the second part will only be evaluated if the first part fails.
function(){
_imaboolean || ($element.removeClass("hidden").addClass("visible"), this.imaboolean = !0)
}
Let's break this down. First we see the || operator, so we have (statement) || (anotherStatement). The way || works is that it evaluates the first statement. If that evaluates to true, it short-circuits and does not evaluate the second statement. The first statement is just _imaboolean. If that's a truthy value (i.e., not 0 or false or undefined...), then we stop right there and don't go to the second statement.
The second statement is
($element.removeClass("hidden").addClass("visible"), this.imaboolean = !0)
Again, there's two statements, separated by a comma. The comma operator evaluates BOTH statements, and returns the last one. So it evaluates $element.removeClass("hidden").addClass("visible") (which sets some classes on $element), and then it evaluates this.imaboolean = !0 (which sets this.imaboolean to a truthy value). The next time this function is run, it will short circuit due to the || operator.

Categories

Resources