Is {} == true or not in javascript? - javascript

Can someone explain why in javascript,
alert({} == true) shows false
if ({}) alert('true') shows true ?
What's different in the if condition that changes the result?
I wanted to write some shorthand argument validator obj || (obj = {}); and I was baffled by this discovery.

if ({}) alert('true') -> true
{} is an object, which, when evaluated in the context of an if statement, gets coerced to a Boolean, and since Boolean({}) evaluates to true, you get if (true). This is documented in the ECMAScript specification, Section 12.5 The if Statement:
The production If Statement : if ( Expression ) Statement is evaluated
as follows:
Let exprRef be the result of evaluating Expression.
If ToBoolean(GetValue(exprRef)) is false, return (normal, empty, empty).
Return the result of evaluating Statement.
alert({} == true) -> false
This one is more tricky. From the ECMAScript specification, Section 11.9.3 The Abstract Equality Comparison Algorithm:
The comparison x == y, where x and y are values, produces true or false. Such a comparison is performed as follows:
If Type(y) is Boolean, return the result of the comparison x == ToNumber(y).
Thus, {} == true will be evaluated as {} == Number(true), which is evaluated to {} == 1, which is false.
This is also why 1 == true evaluates to true, but 2 == true evaluates to false.

{} is not true so it won't show up in your first example. In your second example {} is not false so it will pass the test.
Like my teacher used to say, you can't compare potatoes and carrots.
It's not only with arrays, it will work with anything:
alert(3 == true); // shows false
if (3) alert('true'); // shows true

In boolean operations, generally anything that is not 0 evaluates to true.
http://jsfiddle.net/QF8GW/
if (0) console.log("0 shows true"); // does not log a value
if (-1) console.log("-1 shows true");
if (12345) console.log("12345 shows true");
if ({}) console.log("{} shows true");
if ([]) console.log("[] shows true");
All of these except 0 will evaluate to true.
However, their values, when compared to true will not evaluate to true.
// logs the statement (1 and true are the same.)
​if (1 == true) console.log("1==true shows true");​​​​​​​​
if (12345 == true) console.log("12345==true shows true"); // does not log

I tried in jsfiddle.net and only try in the first alert says false, the IF does not alert true.

alert({} == true) //display "false"
if({} == true)
{
alert("it's true");
}else
{
alert("it's false"); // <-- alert this
}
( snippet )

Related

Why ![] and [] == false yelds different results? [duplicate]

Empty arrays are true but they're also equal to false.
var arr = [];
console.log('Array:', arr);
if (arr) console.log("It's true!");
if (arr == false) console.log("It's false!");
if (arr && arr == false) console.log("...what??");
I guess this is due to the implicit conversion operated by the equality operator.
Can anyone explain what's going on behind the scenes?
You're testing different things here.
if (arr) called on object (Array is instance of Object in JS) will check if the object is present, and returns true/false.
When you call if (arr == false) you compare values of this object and the primitive false value. Internally, arr.toString() is called, which returns an empty string "".
This is because toString called on Array returns Array.join(), and empty string is one of falsy values in JavaScript.
Regarding the line:
if (arr == false) console.log("It's false!");
Maybe these will help:
console.log(0 == false) // true
console.log([] == 0) // true
console.log([] == "") // true
What I believe is happening is that the boolean false is coerced to 0 for comparison with an object (the left-hand side). The object is coerced to a string (the empty string). Then, the empty string is coerced into a number, as well, namely zero. And so the final comparison is 0 == 0, which is true.
Edit: See this section of the spec for details on exactly how this works.
Here's what's happening, starting at rule #1:
1. If Type(x) is different from Type(y), go to step 14.
The next rule that applies is #19:
19. If Type(y) is Boolean, return the result of the comparison x ==
ToNumber(y).
The result of ToNumber(false) is 0, so we now have:
[] == 0
Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #21:
21. If Type(x) is Object and Type(y) is either String or Number, return the
result of the comparison
ToPrimitive(x)== y.
The result of ToPrimitive([]) is the empty string, so we now have:
"" == 0
Again, rule #1 tells us to jump to step #14, but the next step that actually applies is #17:
17. If Type(x) is String and Type(y) is Number, return the result of the
comparison ToNumber(x)== y.
The result of ToNumber("") is 0, which leaves us with:
0 == 0
Now, both values have the same type, so the steps continue from #1 until #7, which says:
7. If x is the same number value as y, return true.
So, we return true.
In brief:
ToNumber(ToPrimitive([])) == ToNumber(false)
To supplement Wayne's answer and to try to explain why ToPrimitive([]) returns "", it's worth considering two possible types of answers to the 'why' question. The first type of answer is: "because the specification says this is how JavaScript will behave." In the ES5 spec, section 9.1, which describes the result of ToPrimitive as a default value for an Object:
The default value of an object is retrieved by calling the [[DefaultValue]] internal method of the object, passing the optional hint PreferredType.
Section 8.12.8 describes the [[DefaultValue]] method. This method takes a "hint" as an argument, and the hint can be either String or Number. To simplify the matter by dispensing with some details, if the hint is String, then [[DefaultValue]] returns the value of toString() if it exists and returns a primitive value and otherwise returns the value of valueOf(). If the hint is Number, the priorities of toString() and valueOf() are reversed so that valueOf() is called first and its value returned if it's a primitive. Thus, whether [[DefaultValue]] returns the result of toString() or valueOf() depends on the specified PreferredType for the object and whether or not these functions return primitive values.
The default valueOf() Object method just returns the object itself, which means that unless a class overrides the default method, valueOf() just returns the Object itself. This is the case for Array. [].valueOf() returns the object [] itself. Since an Array object is not a primitive, the [[DefaultValue]] hint is irrelevant: the return value for an array will be the value of toString().
To quote David Flanagan's JavaScript: The Definitive Guide, which, by the way, is a superb book that should be everyone's first place to get answers to these types of questions:
The details of this object-to-number conversion explain why an empty array converts to the number 0 and why an array with a single element may also convert to a number. Arrays inherit the default valueOf() method that returns an object rather than a primitive value, so array-to-number conversion relies on the toString() method. Empty arrays convert to the empty string. And the empty string converts to the number 0. An array with a single element converts to the same string that that one element does. If an array contains a single number, that number is converted to a string, and then back to a number.
The second type of answer to the "why" question, other than "because the spec says", gives some explanation for why the behavior makes sense from the design perspective. On this issue I can only speculate. First, how would one convert an array to a number? The only sensible possibility I can think of would be to convert an empty array to 0 and any non-empty array to 1. But as Wayne's answer revealed, an empty array will get converted to 0 for many types of comparisons anyway. Beyond this, it's hard to think of a sensible primitive return value for Array.valueOf(). So one could argue that it just makes more sense to have Array.valueOf() be the default and return the Array itself, leading toString() to be the result used by ToPrimitive. It just makes more sense to convert an Array to a string, rather than a number.
Moreover, as hinted by the Flanagan quote, this design decision does enable certain types of beneficial behaviors. For instance:
var a = [17], b = 17, c=1;
console.log(a==b); // <= true
console.log(a==c); // <= false
This behavior allows you to compare a single-element array to numbers and get the expected result.
console.log('-- types: undefined, boolean, number, string, object --');
console.log(typeof undefined); // undefined
console.log(typeof null); // object
console.log(typeof NaN); // number
console.log(typeof false); // boolean
console.log(typeof 0); // number
console.log(typeof ""); // string
console.log(typeof []); // object
console.log(typeof {}); // object
console.log('-- Different values: NotExist, Falsy, NaN, [], {} --');
console.log('-- 1. NotExist values: undefined, null have same value --');
console.log(undefined == null); // true
console.log('-- 2. Falsy values: false, 0, "" have same value --');
console.log(false == 0); // true
console.log(false == ""); // true
console.log(0 == ""); // true
console.log('-- 3. !NotExist, !Falsy, and !NaN return true --');
console.log(!undefined); // true
console.log(!null); // true
console.log(!false); // true
console.log(!""); // true
console.log(!0); // true
console.log(!NaN); // true
console.log('-- 4. [] is not falsy, but [] == false because [].toString() returns "" --');
console.log(false == []); // true
console.log([].toString()); // ""
console.log(![]); // false
console.log('-- 5. {} is not falsy, and {} != false, because {}.toString() returns "[object Object]" --');
console.log(false == {}); // false
console.log({}.toString()); // [object Object]
console.log(!{}); // false
console.log('-- Comparing --');
console.log('-- 1. string will be converted to number or NaN when comparing with a number, and "" will be converted to 0 --');
console.log(12 < "2"); // false
console.log("12" < "2"); // true
console.log("" < 2); // true
console.log('-- 2. NaN can not be compared with any value, even if NaN itself, always return false --');
console.log(NaN == NaN); // false
console.log(NaN == null); // false
console.log(NaN == undefined); // false
console.log(0 <= NaN); // false
console.log(0 >= NaN); // false
console.log(undefined <= NaN); // false
console.log(undefined >= NaN); // false
console.log(null <= NaN); // false
console.log(null >= NaN); // false
console.log(2 <= "2a"); // false, since "2a" is converted to NaN
console.log(2 >= "2a"); // false, since "2a" is converted to NaN
console.log('-- 3. undefined can only == null and == undefined, and can not do any other comparing even if <= undefined --');
console.log(undefined == null); // true
console.log(undefined == undefined); // true
console.log(undefined == ""); // false
console.log(undefined == false); // false
console.log(undefined <= undefined); // false
console.log(undefined <= null); // false
console.log(undefined >= null); // false
console.log(0 <= undefined); // false
console.log(0 >= undefined); // false
console.log('-- 4. null will be converted to "" when <, >, <=, >= comparing --');
console.log(12 <= null); // false
console.log(12 >= null); // true
console.log("12" <= null); // false
console.log("12" >= null); // true
console.log(0 == null); // false
console.log("" == null); // false
console.log('-- 5. object, including {}, [], will be call toString() when comparing --');
console.log(12 < {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log(12 > {}); // false, since {}.toString() is "[object Object]", and then converted to NaN
console.log("[a" < {}); // true, since {}.toString() is "[object Object]"
console.log("[a" > {}); // false, since {}.toString() is "[object Object]"
console.log(12 < []); // false, since {}.toString() is "", and then converted to 0
console.log(12 > []); // true, since {}.toString() is "", and then converted to 0
console.log("[a" < []); // false, since {}.toString() is ""
console.log("[a" > []); // true, since {}.toString() is ""
console.log('-- 6. According to 4 and 5, we can get below weird result: --');
console.log(null < []); // false
console.log(null > []); // false
console.log(null == []); // false
console.log(null <= []); // true
console.log(null >= []); // true
In if (arr), it is always evaluated (ToBoolean) to true if arr is an object because all objects in JavaScript are truthy. (null is not an object!)
[] == false is evaluated in iterative approach. At first, if one side of == is primitive and the other is object, it converts object to primitive at first, then converts both sides to Number if both sides are not string (string comparison is used if both sides are strings). So the comparison is iterated like, [] == false -> '' == false -> 0 == 0 -> true.
Example:
const array = []
const boolValueOfArray = !!array // true
It happens because
ToNumber(ToPrimitive([])) == ToNumber(false)
[] is empty Array object → ToPrimitive([]) → "" → ToNumber("") → 0
ToNumber(false) → 0
0 == 0 → true
An array with elements (regardless if 0, false or another empty array), always resolves to true using Abstract Equality Comparison ==.
1. [] == false; // true, because an empty array has nothing to be truthy about
2. [2] == false; // false because it has at least 1 item
3. [false] == false; // also false because false is still an item
4. [[]] == false; // false, empty array is still an item
But using a Strict Equality Comparison ===, you are attempting to evaluate the variable's content as well as its data type that is why:
1. [] === false; // false, because an array (regardless of empty or not) is not strictly comparable to boolean `false`
2. [] === true; // false, same as above, cannot strictly compare [] to boolean `true`
3. [[]] === false; // true, because see #1
It seems no one is talking about why
(arr && arr == false) is true. Just for people who are not sure about the operator precedence, accourding to MDN, == has higher precedence than &&, so it is actually (arr && (arr == false)). After wildcard's answer , it's true && true, so it's true.
var arr = [];
if (arr && arr == false) console.log("...what??");
You can empty a JavaScript Array by referencing it to a new array, using list = [] or deleting the elements of the currently referenced array list.length = 0.
Source: JavaScript Empty Array
None of the above helped me, when trying to use the knockout.js mapping plugin, perhaps since an "empty array" isn't really empty.
I ended up using: data-bind="if: arr().length" which did the trick.
This is specific to knockout, not the OP's question, but maybe it will help someone else browsing here in a similar situation.

Javascript AND OR operators and parentheses

Having issues correctly triggering code in an if and or statement. I want the code in the statement to run when the defholdid var is equal to "cb_SR" AND if ANY of these variables are true: altRighttargets, inRightTargets, safetyRightTargets. I have checked each variable on their own and they all receive the values I expect. Here's the statement:
if (defholdid === "cb_SR" && (altRightTargets === true || inRightTargets === true || safetyRightTargets === true)) {
//code I want to trigger
};
I checked the statement with each individual expression, and I can get the code to trigger, so I think I'm incorrectly writing the statement.
Thanks,
Make sure that the variables you're comparing with true actually hold boolean values, not strings "true" or "false". If they contain these strings, the comparison with true will always be false. In the context of your OR grouping, that variable is effectively ignored.
The strict equality operator === will always be false for values of different types. But even if you change to the loose equality operator ==, true == "true" will be false. When comparing a boolean with another type, the boolean is converted to 0 or 1 first, and then this is compared with the other value (with additional type juggling possible). So true == "1" is true because 1 == "1", but true == "true" is false because 1 == "true" is false. As pointed out in this answer, we have the following cases of comparing a boolean with a string:
true == "true"; //false
true == "1"; //true
false == "false"; //false
false == ""; //true
false == "0"; //true

Empty array returning false when compare but when it is alone returning true...why like this

if([]==true) //evalutes as false
//when i check empty array with true, if evaluating [] as false so it
if condition return false
if([]) //evalutes as true
//when i check empty array alone, if evaluating [] as true so it if
condition return true
why it is evaluating like that?
thanks
Based on abstract equality comparison algorithm your first code will be evaluated like below,
step 1 : ToNumber([]) == true
step 2 : ToPrimitive([]) == true
(ToNumber() will call ToPrimitve() when the passed argument is an object)
step 3 : "" == true
step 4 : 0 == true
step 5 : false == true
step 6 : false
And in your second case, [] is a truthy value, so if([]) will be evaluated to true always, here [] will not be converted as a primitive. Abstract equality comparison algorithm comes into play when you use == operator.
Another better example would be,
var x = [] || "hello";
console.log(x); // []
Since [] is a truthy value, x would be set with [] not "hello"
When you use only a variable as the condition (without comparison operators), Javascript will cast it to Boolean using the Boolean() function:
http://www.w3schools.com/js/js_booleans.asp
In your case, Boolean([]) = true so it returned as true.

what does && return in javascript expression

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.

Why is this boolean casting not working as expected?

I've just answered this question but I don't understand why it works the way it does.
Basically the problem can be simplified to this:
var b = new Boolean(false);
console.info(b == false); // Prints "true" - OK
console.info(b && true); // Prints "true" - but should be "false"
I assume there's some unintuitive automatic casting going on but I don't understand it would sometime be automatically casted to true, sometime to false. Any idea?
I guess this illustrates the problem better:
> false && 123
false // OK
> new Boolean(false) && 123
123 // ???
== does a lot of coercion:
Object == false =>
Object == 0 =>
Object.valueOf() == 0 =>
false == 0 =>
0 == 0 =>
true
Or if you follow the steps in the algorithm, it is
Step 7, Step 9, Step 6, Step 1 c iii.
The logical and just goes directly for ToBoolean, which always returns true for objects.
Note that new Boolean returns an object and not a boolean value.
Maybe the object b is true when doing (b && false) but doing to logical operation of true and false results to false.
If you do this:
var b = new Boolean(false);
console.info(b == false); // Prints "true" - OK
console.info(b && true); // Prints "true"
So even though the object b was set to false in the (b && true) it results to true because it exists and it's not set to null.
False AND False is false. Truth tables - AND only returns true if both arguments are true, and neither is in this case.
EDIT: True AND False is also false, so anything && False is false.
I'm not sure if I understand your question correctly but it look like the major issue derives from the fact that if (new Boolean(false)) evaluates to true. If you put expressions in an if statement or link them with logical operators (i.e. &&), JavaScript only checks if they are truthy or falsy. When it comes to boolean primitives, it is easy:
true -> truthy
false -> falsy
But when it comes to boolean objects, it looks different:
new Boolean(false) -> truthy
new Boolean(true) -> truthy
The reason for this is, that in JavaScript, every object (if not null) is truthy.

Categories