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.
Related
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.
Sorry if this question is not upto the level of the site i cannot find help anywhere else. I have just started to learn JavaScript but i am stuck at an example code given in my text-book
var a = null;
function b() {return "B";}
(a || b)();
! "B"
There is not enough explanation given for the code and i am not able to figure out how does it work, can anyone help me please
Thanks
Akash
I assume the source of your confusion comes from the third and fourth line.
Let's start with the third line: (a || b)();.
First a is evaluated and if it is not null or undefined then the result of this expression is a(), otherwise the result is b().
In your code snippet, a is null, so the expression is evaluated to b() which simply returns "B".
The OR || operator looks at its operands one by one, until it finds a value that is truthy and it returns it, if all the values are falsy then the last operand is returned.
For more information about truthy and falsy values, check here
Now this line ! "B", all strings in JavaScript are evaluated to true except for the empty string "", so the result of the previous expression is ! true so it is false.
The key is in how the || operator works. This line:
(a || b)();
is equivalent to this:
var f;
if (a)
f = a;
else
f = b;
f();
The || operator works by first evaluating the left side (in this case, a). It then checks to see whether that value is "truthy", which means that it's not null, 0, the empty string, and a couple other things. In this case it's clearly null, so it's not "truthy".
Thus the || operator goes on to evaluate the right side (in this case, b), and that value is taken as the result of the || operation. What's "b"? It's that little function that returns the string "B" when called.
Thus after the || operation is done, you're left with a reference to that function, and the subsequent () function call operator causes that function to be called.
There are two variables, a which is null and b which is a function that always returns the string "B". (a || b)() demonstrates a bit how logical && and || work in JavaScript - the evaluation is short-circuited and the last value evaluated is the value of the entire expression. Since a is null which is falsy, (a || b)() evaluates to b(), so you get the "B" print.
In general:
(a || b); //a if a is truthy, otherwise b
(a && b); //a if a is falsy, otherwise b
Falsy values are null, undefined, 0, the empty string "", NaN and of course false. Everything else is truthy.
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
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
&& operator in Javascript
In the sample code of the ExtJS web desktop demo there is the following call:
this.setActiveButton(activeWindow && activeWindow.taskButton);
to method:
setActiveButton: function(btn) {
if (btn) {
btn.toggle(true);
} else {
this.items.each(function (item) {
if (item.isButton) {
item.toggle(false);
}
});
}
}
What is the purpose of the && in the function call?
It's to make sure that, before trying to find a property on an object referenced by the variable "activeWindow", the variable actually does reference something. If it's null (or a few other things; we'll assume the code knows that it's either an object reference or null), that would cause an exception. This way, the function is passed either the button reference (whatever that is), or null.
To put it another way, it's the same as this:
this.setActiveButton(activeWindow != null ? activeWindow.taskButton : null)
The && operator in JavaScript is kind-of special compared to the && in C or Java or other languages like that. In JavaScript, the left side is evaluated first. If that value is "falsy" (null, undefined, false, zero, or an empty string), then that's the value of the expression. Otherwise, the value of the expression is the value of the right-hand side.
See Short-circuit evaluation for additional information regarding this method.
The short-circuit expression x Sand y (using Sand to denote the
short-circuit variety) is equivalent to the conditional expression if
x then y else false; the expression x Sor y is equivalent to if x then
true else y.
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;
}