Why does the following code produce a == 3?
var x = "abc";
var y = 3;
var z = "xyz";
var a = x && y || z;
http://jsfiddle.net/thinkingmedia/qBZAL/
I would have expected this to result in a == true.
Why is the logical operator evaluating "abc" as true but doesn't evaluate 3 as true. Instead it produces 3 as the result.
Furthermore, if you change y = 0 then a == "xyz" which means that && treated 0 as false. What happen to treating a number as a number?
What's going on here with the logical operators?
This is to be expected.
In JavaScript (and many other languages), not only Booleans themselves are true or false, but other objects can be truthy or falsey as well (See the docs on mdn):
The value […] is converted to a boolean value, if necessary. If value is […] is 0, -0, null, false, NaN, undefined, or the empty string (""), [it is] false. All other values, including any object or the string "false", create […] true.
The logical operators || and && don't return true or false, rather they return the last argument to influence whether they are truthy or falsey (reference):
expr1 && expr2 – Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
expr1 || expr2 – Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.
The first step is to evaluate "abc" && 3.
false && 3 would return false,
true && 3 would return 3.
"abc" is not false, so JavaScript takes the second part, i.e. 3.
The second step is to evaluate 3 || "xyz". Here, JavaScript takes the first value which is not null, i.e. 3. This is similar to this.firstObject ?? this.defaultValue in C#: the second part is taken only when the first part is null.
the side effect is that you can do things like this:
x = x || {};
to set a variable to a default if it is not set.
Or
TrackingManager && TrackingManager.track("user was here")
to avoid bulkier if statements.
Related
I am currently reading JavaScript from JavaScript: The Definitive Guide. On page 76, there is this statement written,
o && o.x // => 1: o is truthy, so return value of o.x
Being a Java programmer I want to ask, why is it returning 1 instead of 'true' In Java this was not the case, but anyway I know JavaScript is different but the Logical AND mechanism is the same everywhere.(In C it returns 1 as true.)
I am asking is, why does it makes sense for this behavior at all?
Is there any way, I can ensure to return only the true or false values?
As per the Spec for Binary Logical Operators
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.
This is a feature used in javascript a lot, one common use case is to assign a default value to a variable if it is not defined. Like assume you are expecting a options object as a param but is not mandatory so the user may not pass it
function x(options){
options = options || {};
//now your can access optionx.a without fearing whether options is undefined
}
You can do something like !!(o && o.x) to always get a true/false
if we have:
expr1 && expr2
&& Returns 'expr1' if it can be converted to false; otherwise, returns 'expr2'. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
So if we have:
Var xyz = a && b; //where a is undefined(false) and b is 123, then it will allocate undefined.
In case of if statements, these values are specifically converted to boolean.
Refer the following link: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Logical_Operators"
You can use Boolean(o && o.x); to get true or false
It's returning the value of the right operand. If the value of o.x was true, it would return true. If the value of o.x was 'banana', it would return 'banana'.
var o = {x:true};
console.log(o && o.x);
Technically && operator implemented to return the first operand if it's value is not zero, and returns the second operand otherwise in a lot of languages including Java, C/C++, Javascript, Perl...
While most of the languages accepts any type of operands, Java forces you to use boolean operands so it always returns true or false.
In order to force a boolean result in Javascript use:
Boolean(a && b)
This behaviour is called coercion. Coercion is the action of forcing an object to behave like other type, and the logical operators can produce coercion when trying to access the value of the object to be evaluated.
It is important to remember the table for truthy and falsy values, because due to coercion, different results can be obtained.
false produces false
0 produces false
“” produces false
NaN produces false
null produces false
undefined produces false
Everything else produces true, including the text "0" and "false", functions, arrays and empty objects.
Given the rules for logic operators, exists short-circuit evaluation in JavaScript, e.g:
0 && 1; //-> 0, falsy value
!(0 && 1); //-> true, falsy value negated
!!(0 && 1); //-> false, boolean falsy value
void 0 && alert("1") //-> undefined (void produces undefined)
[] && Math.ceil(9.1) //-> 10, truthy value
{} && someFunc() //-> the result of someFunc()
0 || null; //-> null, falsy value
null || "0"; //-> "0", truthy value
"" || void 1; //-> undefined, falsy value
!!(+"5px" || {}); //-> true, boolean truthy value
Coercion is useful when you have to validate default values, in order to prevent errors, e.g.
function divide (a, b) {
a = +a; //-> coerced to number
b = +b; //-> coerced to number
if (!a) return 0; //-> NaN or zero
return b && a / b; //-> b must be a number different from zero
}
divide(); //-> 0
divide(5); //-> NaN, no error thrown!
divide(5, "a"); //-> NaN, no error thrown!
divide(5, 0); //-> 0, division by zero prevented!
divide(49, 6); //-> 8.1666
If you want to prevent returning NaN, just add another coercion in the return statement:
return (b && a / b) || 0;
You can check other coercion cases: JavaScript Coercion
Happy coding!
In these example I am ruining a function with conditions;
function validPrice(price)
{
if(price=="" || price==0 || price==null || price==undefined )
{
//do something
}
else
{
// do something different
}
}
var priceNew = $("li#listedProd").attr("price");
validPrice(priceNew);
My question is what are the different in these condition price=="" || price==0 || price==null || price==undefined
Whoever first wrote that code was either
a) Being very defensive against future use.
b) Didn't understand how attr works.
The method attr (or the underlying call of getAttribute will return either
A string value, of the attribute is found
null, if it is not.
Importantly, should there have been a 0 value, it would be a string 0, and thus not caught in the test below -- caught against the price == 0 test because the system would have automatically converted it to a number as part of the == compare.
if(price=="" || price==0 || price==null || price==undefined )
And, due to the way that conversions work internally, those tests don't work as intended. == and === are different. It should be:
if(price === "" || price === 0 || price === null || price === undefined )
All of which can easily be reduced to simply "price" due how how coercion to boolean work:
if (!price)
Or, if you want to catch "0" values
if (!price || +price === 0)
(the +price forces price to be a number, so we catch 0 0.00 and other variations.)
Let's look at your conditional statement term-by-term:
price == ""
This is true if price is the empty string, and false otherwise.
price == 0
This is true if price is the integer 0, the string "0", or the empty string, and false otherwise. You should change this comparison to price === 0 if you want to catch when price is the integer 0.
price == null
This is true if price is passed to your function and is of the type null, and false otherwise.
price == undefined
Note: You should probably make this comparison via price === undefined to see that price is both undefined and has the type undefined.
This is true if price is not passed to your function, or if price is otherwise undefined, and false otherwise.
I would recommend just making the entire conditional statement !price:
function validPrice(price) {
if (!price) {
//do something
}
else {
// do something different
}
};
var priceNew = $("li#listedProd").attr("price");
validPrice(priceNew);
EDIT added definitions
JavaScript has 2 operators that test for equality (and conversely 2 operators that test for inequality.)
A strict equality comparison (e.g., ===) is only true if the operands are of the same type AND if the object is actually the same object, or the primitives have the same value (e.g., 0 === 0, and 'a' === 'a' are both true). *Note there is a slight exception to this rule for NaN (see below)
An abstract equality comparison (e.g. ==) converts the operands to the same Type (if they aren't already) before making a strict equality comparison. If however one of the operands is null or undefined, the comparison is true if and only if the other operand is either null or undefined.
So in short the == equality operator is considered by many to be unsafe. To see the difference checkout http://dorey.github.io/JavaScript-Equality-Table/
For instance '' ==: 0, '', [], false, [[]]
And 0 ==: false, 0, '0', '', [], [[]], [0]
While null ==: null, undefined
And finally undefined ==: null, undefined
It is better to use strict equal === or just test for a falsey value ('', 0, undefined, null, false)
if (!price) { //do something }
Below I have provided more details about strict vs abstract equality comparison
details came from ECMA-262, Edition 5 11.9.1
Summary of strict equality algorithm
1. If typeof(x) is different from typeof(y), return false.
2. If typeof(x) is undefined, return true.
3. If x is null, return true.
4. If typeof(x) is number, then
a. If x is NaN, return false.
b. If y is NaN, return false.
c. If x is the same Number value as y, return true.
d. If x is +0 and y is -0, return true.
e. If x is -0 and y is +0, return true.
f. Return false.
5. If typeof(x) is string, then
a. If x and y are exactly the same sequence of characters (same length and same characters in
corresponding positions), return true.
b. Else, return false.
6. If typeof(x) is boolean, then
a. If x and y are both true or both false, return true.
b. Else, return false.
7. If x and y are the same Object value, return true.
8. Return false.
And ... details came from ECMA-262, Edition 5 11.9.1
Summary of Abstract Equality Algorithm
1. If typeof(x) is the same as typeof(y), then
return the result of performing strict equality comparison algorithm x === y.
2. If x is null and y is undefined, return true.
3. If x is undefined and y is null, return true.
4. If typeof(x) is number and typeof(y) is string,
return the result of the comparison x == Number(y).
5. If typeof(x) is string and typeof(y) is number,
return the result of the comparison Number(x) == y.
6. If typeof(x) is boolean, return the result of the comparison Number(x) == y.
7. If typeof(y) is boolean, return the result of the comparison x == Number(y).
8. If typeof(x) is either string or number and typeof(y) is object,
return the result of the comparison x == [[ToPrimitive]](y).
9. If typeof(x) is object and typeof(y) is either string or number,
return the result of the comparison [[ToPrimitive]](x) == y.
10. Return false.
[[ToPrimitive]] is an internal function call
Bullets 8 and 9 basically mean that objects are converted like object.valueOf().toString() so:
{} == '[Object object]'
{ hi: 'hi'} == '[Object object]'
{ valueOf: function(){ return 0; }} == 0
{ toString: function(){ return 'hi'; }} == 'hi'
{ valueOf: function(){ return 0; }, toString: function(){ return 'hi'; }} == 0
Full ecma-262/5.1/#sec-11.9 spec
I was reading the javascipt code in some application and code was this
getTotalFees:function(){
return this.grid
&&this.grid.getStore().sum('fees');
}
Now i am confused what it will return.
IT looks to me like
return a&&b
won't it return true or false rather than b
Logical AND (&&):
expr1 && expr2 Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
Source
So, basically:
If the first parameter is falsy, it returns that parameter. Else, it literally returns the second parameter.
In your case, this means that, if this.grid exists, it returns this.grid.getStore().sum('fees');
This is done to protect against calling a method on undefined property, witch would cause an error. So if this.grid is undefined, then undefined is returned.
In expressions if a && b when a equals to false (or in javascript it can be an expression like in Cerburs answer), then a is returned.
Similarly with || operator, the first from the left that equals to true (in javascript not 0, not undefined, not null, not NaN, and not false of course) is returned.
You misunderstand what && does. Let a and b be "entities". Then a && b does:
evaluate a
if a is falsy return a
if a is truthy evaluate b
return b
Example:
var f = function() {
console.log("test");
return 'foo';
}
> 0 && f()
0
> 1 && f()
test
"foo"
Note that in first case we didn't get console.log because f() was not evaluated because 0 is falsy. This property is important and actually
a && b != b && a
even though mathematically it should be the same (but it is not due to side-effects of evaluation).
Falsy values include: 0, false, "" (empty string), null, undefined,NaN (not a number type). I don't think there are any other possible values (someone correct me if I'm wrong). Every other object is truthy.
So in your case the code can be rewritten as:
if (this.grid) {
return this.grid.getStore().sum('fees');
} else {
return this.grid;
}
Ok, let's assume that this.grid.getStore().sum('fees') returns something, let's say "okay!".
now the return statement in your code is a convoluted way of saying :
if(this.grid)//this.grid is defined and doesn't evaluate as 'false'
return this.grid.getStore().sum('fees');
else
return this.grid;
if this hasn't got a grid, we return undefined, else we call gridStore... and return its own return.
It is a common way of avoiding "undefined has no method 'gridStore'"
the VERY important part is that, in a && f(), f() will NOT be called if 'a' evaluates to false. there are many things that evaluate to false, such as any undefined variable, null, empty strings... (note that strings that contain falsy things like "false" or "0000" are actually truthy). or even unreadable babble like function(){return null;}(); may evaluate as false.
I have a method hitTest that check for collision detection and can return a Point object (if a collision is happened) or (if there is no collision) it returns null or undefined (i haven't deeply understand when it return null or undefined but i trust chrome console).
I have to test collision on 2 objects. And check if one or the two collisions are happening. I have tried this code:
var result1 = hitTest(player, object1);
var result2 = hitTest(player, object2);
if( result1 || result2 ) { blabla() };
but it doesn't work.
now.. i know that js is reallly a tricky language and i think about a smart way to do this without writing typeof 4 times. I'm thinking about python short-circuit logical operators...
You can use &&, it returns the first detected false/null/undefined/0, i.e. if won't pass, if either result1 or result2 is null.
for this type of thing, underscore.js is beautifull: http://underscorejs.org/#isNull and http://underscorejs.org/#isUndefined
I use these helpers frequently to get around edge cases in JS such as the ones you mentioned
You wouldn't need to write typeof 4 times already but anyway;
Coercion paradigm for conditional statements and operators:
//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
From Mozilla:
Logical AND (&&)
expr1 && expr2
If the first operand (expr1) can be converted to false, the && operator returns false rather than the value of expr1.
Logical OR (||)
expr1 || expr2
Returns expr1 if it can be converted to true; otherwise, returns expr2. Thus, when used with Boolean values, || returns true if either operand is true; if both are false, returns false.
true || false // returns true
true || true // returns true
false || true // returns true
false || false // returns false
"Cat" || "Dog" // returns Cat
false || "Cat" // returns Cat
"Cat" || false // returns Cat
true && false // returns false
true && true // returns true
false && true // returns false
false && false // returns false
"Cat" && "Dog" // returns Dog
false && "Cat" // returns false
"Cat" && false // returns false
Additionally, you can use a shortcut isset() method just like in PHP to properly validate your objects:
function isSet(value) {
return typeof(value) !== 'undefined' && value != null;
}
So; your code would be:
var result1 = hitTest(player, object1),
result2 = hitTest(player, object2);
if ( isSet(result1) && isSet(result2) ) { blabla(); };
I have been using MDN Docs - Logical Operators as a frame of reference to understand the logical AND operator.
I have understood most of these code examples especially the first 4 as shown here:
a1=true && true // t && t returns true
a2=true && false // t && f returns false
a3=false && true // f && t returns false
a4=false && (3 == 4) // f && f returns false
a5="Cat" && "Dog" // t && t returns Dog
a6=false && "Cat" // f && t returns false
a7="Cat" && false // t && f returns false
However I am having issue understanding a5, a6 and a7.
I am failing to understand how the two strings a5="Cat" && "Dog" are evaluating to true && true returns Dog
I am also failing to understand why the string "Cat" is evaluating to true as part of a6=false && "Cat" // f && t returns false
All non-empty strings are true when evaluated as boolean values.
In a6=false && "Cat" the string "Cat" is not evaluated at all, as the left side is false.
First of all lets look at a5:
a5="Cat" && "Dog"
Which returns dog, the mdn-docs states that AND(&&):
Returns expr1 if it can be converted to false; otherwise, returns expr2. Thus, when used with Boolean values, && returns true if both operands are true; otherwise, returns false.
Since a non-empty string can't be converted to false, it will return dog, if you change the order of dog and cat, it will ofcourse return cat.
In a6 false, is false and thus it returns false because of this:
Returns expr1 if it can be converted to false...
In a7 cat is true and thus it goes on to the next expression which is false, and thus returns false.
...otherwise, returns expr2
In a && b sentence a is evaluated first, and if a is true, then b is evaluated.
(a5 = "Cat") returns "Cat" which is true (only empty strings are false), so Dog is returned.
(a6 = false) returns false, so the second "Cat" part is not evaluated.
(a7 = "Cat") is true, so the second false part is returned.