Is this normal? Is it a feature or a bug? (I'm using firebug):
>>> '' || true
true
>>> '' || false
false
>>> '' && false
""
>>> '' && true
""
It is not converting the empty string to Boolean.
With ||
It is evaluating the left hand side, of which an empty string is falsy. It then checks the right hand side (because it's an or, and that side may be true), and returns that value.
With &&
Because && needs both sides to be true and the left hand side is falsy, it doesn't bother checking the right hand side (short circuit evaluation). Therefore, it just returns the left hand side, which is the empty string.
JavaScript always returns the last value it evaluated.
>>> '' || 0 || undefined || null || false || NaN || 'hello'
"hello"
It's not that one is converting and the other isn't; the lines with || are returning their second operand and the lines with && are returning their first, due to short-circuiting.
[ECMA-262 11.11]: Semantics
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).
The production LogicalORExpression : LogicalORExpression ||
LogicalANDExpression is evaluated as follows:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
The LogicalANDExpressionNoIn and LogicalORExpressionNoIn
productions are evaluated in the same manner as the
LogicalANDExpression and LogicalORExpression productions except
that the contained LogicalANDExpressionNoIn,
BitwiseORExpressionNoIn and LogicalORExpressionNoIn are evaluated
instead of the contained LogicalANDExpression, BitwiseORExpression
and LogicalORExpression, respectively.
NOTE The value produced by a && or || operator is not necessarily
of type Boolean. The value produced will always be the value of one of
the two operand expressions.
The || operator will return the first value which is truthy.
The && operator will return the second value if the first is truthy, otherwise it returns the first.
For more info, you can see the Logical Operators page on the MDC site.
In your case,
'' || true; '' is false, so the || operator moves onto the second value, which is true, and so returns it.
'' || false; '' is false, so the || operator moves onto the second value, which is false, and has no more values to compare, so returns it.
'' && false; the first value ('') is falsy, so it returns it.
'' && true; the first value ('') is falsy, so it returns it.
Related
Why is the mid number result of this statement?
(0 || 0.571428571428571 || 1) == 0.571428571428571
How the comparsion works?
Well. Looks like stupid question. For those who works in php where this statement has a different result could be helpfull to know that JS will return number instead bool.
|| is a short-circuiting operator. It evaluates its left-hand operand, and returns that if it's truthy, otherwise it evaluates and returns its right-hand operator. When you have a sequence of || operators, it performs this left-to-right, returning the first truthy value (or the last value if none are truthy).
In your example, 0 is falsey, so 0.571428571428571 is the first truthy value, and it's returned.
Your expression is interpreted as
((0 || 0.571428571428571) || 1)
The result of the first || is truthy, so that's the result of the overall expression. That's how || works: the result is the left-hand operand if it's truthy, or else the right-hand operand.
The answer to this lies in the fact that 0 is considered a false value while non-zero numbers are considered true.
Since || and && will short circuit and return as soon as it knows the outcome. For OR expressions this means that the first truthy value will be returned. For AND expressions it means the first false value is returned:
(true && true && 0 && true) === 0
(false && false && 1) === 1
(false || false || 1 || false) === 1
(false || false || 0) === 0
Since the first value in your expression is a falsey value, it is not returned but the floating point is a truthy value, so it is returned.
Today I came across the strange behaviour in Javascript. Below is the code
return "" && false
returns "".
Why it behaves so ?
Because
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).
ECMAScript 5.1
This means:
Return the first value if it is falsy, return the second value if the first is truthy.
This is also the behavior seen if you do:
return false && true
You get false.
This means also that this
return 23 && "Hello"
would give you "Hello"
The LHS is run first and the return exits you from the function
Specifically (I don't know if it can happen in others case), when I do int(0) && boolean with myString.length && myString === "true" when myString = "", it returns 0 instead of returns a boolean.
alert((function() {
var myString = "";
return myString.length && myString === "true";
})());
I know that I can fix it by do myString.length !== 0 or casting with Boolean. But I like to understand why && don't force cast the left side to boolean.
Live example: http://jsfiddle.net/uqma4ahm/1/
The && operator in JavaScript returns the actual value of whichever one of its subexpression operands is last evaluated. In your case, when .length is 0, that expression is the last to be evaluated because 0 is "falsy".
The operator does perform a coercion to boolean of the subexpression value(s), but it only uses that result to determine how to proceed. The overall value of the && is thus not necessarily boolean; it will be boolean only when the last subexpression evaluated had a boolean result.
This JavaScript behavior is distinctly different from the behavior of the similar operator in C, C++, Java, etc.
The && operator yields the left hand value if it is false-y1 and the right-hand value otherwise. (Unlike some languages, it is not guaranteed to evaluate to true or false!)
TTL for A && B:
A B (A && B)
false-y - A
truth-y - B
To make sure that only true or false is returned, it is easy to apply (double) negation:
return !!(myString.length && myString === "true")
or, equivalently
return !(!myString.length || myString !== "true")
Here is the negation TTL which leads to deriving !!(false-y) => false and !!(truth-y) => true.
A !A !(!A)
false-y true false
truth-y false true
1 In JavaScript the false-y values are false 0, "", null, undefined, NaN. While everything else is truth-y.
Why not zero - which is not a boolean - but a number?
Suppose this example:
var current = 0;
current += Number(3) || Number(4); // now current is 0 + 3 = 3
var current = 0;
current += Number(-3) || Number(4); // now current is 0 + -3 = -3
var current = 0;
current += Number(0) || Number(4); // now current is 0 + 4 = 4
So, in my example it's taking the value to be added which number is not zero.
So, my question is why actually the OR operator || is only taking the value to calculate is rather than zero?
And also,
var current = 0;
current += Number(0) && Number(3); // now current is 0
var current = 0;
current += Number(3) && Number(5); //now current is 5
I'm really confused how the AND and OR operators are working here with the number types (not a Boolean).
Logical operators evaluate both the left and right expressions (if necessary). They both short-circuit immediately. It means that, if the first expression itself is enough to produce the result, irrespective of the other expression, then the other expression will not be evaluated at all. For example, in OR operator, if the first expression is Truthy, then we don't have to evaluate the other expression, the same way, in AND operator, if the first expression is Falsy, we don't have to evaluate the other expression.
Now, we are talking about Truthy and Falsy, right? What are they? When we evaluate an expression, the Truthiness is determined by the following table as per ECMA 5.1 Standard specification,
+-----------------------------------------------------------------------+
| Argument Type | Result |
|:--------------|------------------------------------------------------:|
| Undefined | false |
|---------------|-------------------------------------------------------|
| Null | false |
|---------------|-------------------------------------------------------|
| Boolean | The result equals the input argument (no conversion). |
|---------------|-------------------------------------------------------|
| Number | The result is false if the argument is +0, −0, or NaN;|
| | otherwise the result is true. |
|---------------|-------------------------------------------------------|
| String | The result is false if the argument is the empty |
| | String (its length is zero); otherwise the result is |
| | true. |
|---------------|-------------------------------------------------------|
| Object | true |
+-----------------------------------------------------------------------+
So, unless the number is +0, -0 or NaN, it will be considered Truthy. You can confirm that like this
console.log(Boolean(0));
# false
console.log(Boolean(-1));
# true
console.log(Boolean(100));
# true
That is why OR operator takes the value of the non-zero number.
Quoting from the ECMA 5.1 Specifications for OR Operator,
LogicalANDExpression :
BitwiseORExpression
LogicalANDExpression && BitwiseORExpression
LogicalORExpression :
LogicalANDExpression
LogicalORExpression || LogicalANDExpression
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).
The production LogicalORExpression : LogicalORExpression ||
LogicalANDExpression is evaluated as follows:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
NOTE The value produced by a && or || operator is not necessarily of type Boolean. The value produced will always be the
value of one of the two operand expressions.
The value of an OR statement is determined the moment you encounter "true" (something other than zero.. 'truthy'). Until you encounter that, you need to keep going: maybe one of the other terms is true?
This explains the behavior you are seeing.
current += Number(3) || Number(4) - 3 is true, condition met, no need to look at next term
current += Number(0) || Number(4) - 0 is false, keep going, 4 is true, condition met
From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators
Logical operators are typically used with Boolean (logical) values;
when they are, they return a Boolean value. However, the && and ||
operators actually return the value of one of the specified operands,
so if these operators are used with non-Boolean values, they may
return a non-Boolean value.
I think zero is set to be falsy condtion and all others are set to be truthy condition while we use AND or OR operator for Number.
Consider the following what value does it take to calculate:
Remember 0 is false and all other values (including negative values) are true while we take number.
Also, suppose the followings are the numbers not the booleans.
5 || 0 // true || false returns true, so takes 5
0 || 3 // false || true returns true, so takes 3
4 && 0 // true && false returns false, so takes 0
0 && 6 // false && true returns false, so takes 0
2 && 3 // true && true returns true, which value would take????
// Ummm, last defined value, huh i.e. 3
Flanagan's O'Reilly JavaScript book states:
Unlike the && and || operators, the ! operator converts its operand to
a boolean value [...] before inverting the converted value.
If those logical operators don't convert the operands to booleans, how can the expression be evaluated?
They do convert the values to boolean, but only to determine how to proceed in evaluating the expression. The result of the expression is not necessarily boolean (in fact, if neither of your operands are boolean, it will not give you a boolean):
var x = false || 'Hello' // gives you 'Hello'
var y = 0 && 1 // gives you 0, because 0 is "falsy" and short circuits
var z = 1 || 2 // gives you 1, because 1 is "truthy" and short circuits
Per specification, section 11.11: Binary Logical Operators:
The production [of evaluating &&] ... 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).
The production [of evaluating ||] ... is evaluated as follows:
Let lref be the result of evaluating LogicalORExpression.
Let lval be GetValue(lref).
If ToBoolean(lval) is true, return lval.
Let rref be the result of evaluating LogicalANDExpression.
Return GetValue(rref).
So internally the value is "converted to a boolean". However, since this is never exposed -- and the entire semantic explanation is an abstraction which can be/is "optimized out" -- the behavior of && and || can be simply explained through using truthy-and-falsy values (for which ToBoolean covers: a truthy-value is one for which ToBoolean returns true, all other values are falsy).
The logical table for && is:
a b result
truthy any b
falsy any a
The logic table for || is:
a b result
truthy any a
falsy any b
Note that either the evaluation of a or b is returned.
Happy coding.
For completeness, from section 9.2:
The abstract operation ToBoolean converts its argument to a value of type boolean as ...
Undefined - false
Null - false
boolean (not Boolean object!) - The result equals the input argument (no conversion).
number (not Number object!) - The result is false if the argument is +0, -0, or NaN; otherwise the result is true.
string (not String object!) - The result is false if the argument is the empty String (its length is zero); otherwise the result is true.
Object - true
The operands are interpreted as booleans for evaluating the expression, but the return value of && or || is always one of the operands.
For example:
true && 0 === 0, not false
1 || false === 1, not true
Because JavaScript has an idea of truthiness that covers more than booleans.