JavaScript IF statement boolean strict - javascript

I am setting a mode in a script by passing a "truthy" boolean to a function. In the function a simple if statement checks if the param is true or false. I sometimes pass it as a string or a bool which has always worked, but for some reason it isn't for this:
setMode: function(Setting) {
if (Setting) {
console.log('Enabling mode');
} else {
console.log('Disabling mode');
}
}
For example when I pass it a string 'false' and log Setting to console, the console says false, yet the if statement thinks it's true.
I have to add this to the start of the function for it to work:
if (typeof Setting == 'string') {
Setting = (Setting == "true");
}
An example of it in use:
var inverted = $('INPUT[name="Mode"]').prop('checked');
app.setMode(inverted);
and another:
var mode = localStorage.getItem('Mode');
this.setMode(mode);
It's so bizarre since I've done this type of thing for years yet it's only starting now. Maybe because I'm using localStorage and .prop?

If you try to log 'false' it is obvious that console logs false(it is a string) and that the if statement sees true, because a not-empty string is a true boolean value.
If you want to check if the string is "true" or "false" you have to do it with normal operators. So you could add this line at the beginning of your function:
Setting = (typeof Setting === 'string') ? Setting === "true" : Setting;

To answer your question about string to boolean conversions:
ECMA SPEC:
The result [of this conversion] is false if the argument is the empty String (its length is zero);
otherwise the result is true.
So yes, if you pass the string "false" it will be converted to true, which means the only option you have is to manually check for the strings "true" or "false" and do the conversion by yourself.
However, the jQuery function .prop("checked") is supposed to return a boolean value (or undefined if the property is not defined). So I would say you should be able to actually do
if (elem.prop("checked"))
like here.

For example when I pass it a string 'false' and log it to console, the console says false, yet the if statement thinks it's true.
The console output is confusing, it is concealing the quotes and logging false both for the string "false" and the boolean false. Yet, these two are not equivalent, the string is not empty and indeed truthy.
Maybe because I'm using localStorage and .prop?
Yes. The .checked property returns a boolean and everything works well. In contrast, local storage only stores strings, and when you pass in a boolean you get back its stringification. You can undo that by using
var modeStr = localStorage.getItem('Mode');
var mode = JSON.parse(modeStr);
this.setMode(mode);

Related

How to use localStorage in JavaScript to keep track of a true/false variable? [duplicate]

I noticed that I cannot set boolean values in localStorage?
localStorage.setItem("item1", true);
alert(localStorage.getItem("item1") + " | " + (localStorage.getItem("item1") == true));
Always alerts true | false when I try to test localStorage.getItem("item1") == "true" it alerts true ... How can I set an item in localStorage to true?
Even if it's a string, I thought only === would check the type?
So
alert("true" == true); // should be true?
For the moment, all the implementations Safari, WebKit, Chrome, Firefox and IE, are following the current version of the WebStorage standard, where the value of the storage items can be only a string.
An option would be to use JSON parse and stringify method to serialize and deserialize the data, as I suggested some time ago in another question, for example:
var value = "true";
console.log(JSON.parse(value) === true); // true
Firefox's implementation of Storage can only store strings, but on 2009 September, W3C modified the draft to accept any data. The implementation (still) isn't caught up yet (see Edit below).
So in your case the boolean is converted to a string.
As for why "true" != true, as written in the description of Equal (==) in MDC*:
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible.
Note that the string is converted to a Number instead of a Boolean. Since "true" converted to a number is NaN, it will not be equal to anything, so false is returned.
(*: For the actual standard, see ECMA-262 §11.9.3 “The Abstract Equality Comparison Algorithm”)
Edit: The setItem interface was reverted to accept strings only on the 2011 Sept 1st draft to match the behavior of existing implementations, as none of the vendors are interested in supporting storing non-strings. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 for detail.
My solutions:
function tytPreGetBool(pre) {
return localStorage.getItem(pre) === 'true';
}
This is related to CMS’s answer.
Here’s a little function I’ve been using to handle the parsing part of this issue (the function will keep doing the Right Thing after the browser implementations catch up with the spec, so no need to remember to change out code later):
function parse(type) {
return typeof type == 'string' ? JSON.parse(type) : type;
}
I'd like to point out that it might be kinda easier just to wrap plain boolean value inside object and then, using JSON.stringify create local storage content and other way around, JSON.parse to retrive it:
let storeMe = {
myBool: true
}
localStorage.setItem('test', JSON.stringify(storeMe))
let result = JSON.parse(localStorage.getItem('test'))
Use store.js:
localStorage.setItem('isUser', true)
localStorage.getItem('isUser') === "true" //true
npm i -D store
↓
store.get('isUser') //true
What I usually do is just save the value in LocalStore as a Boolean, and then retrieve with a parsing method, just to be sure for all browsers. My method below is customized for my business logic. Sometimes I might store smth as 'no' and still need false in return
function toBoolean(str) {
if (typeof str === 'undefined' || str === null) {
return false;
} else if (typeof str === 'string') {
switch (str.toLowerCase()) {
case 'false':
case 'no':
case '0':
case "":
return false;
default:
return true;
}
} else if (typeof str === 'number') {
return str !== 0
}
else {return true;}
}
I'm not sure if LocalStorage can save boolean values but I can tell you that when you do alert("true" == true); it will never evaluate to true because you are implicitly comparing a string to a boolean. That is why to set boolean values you use true instead of "true".
eval can also be used carefully under some cases.
console.log(eval("true") === true) //true
When I need to store a flag I usually do:
localStorage.f_active = true (stored value is 'true' and it's fine)
if localStorage.f_active — passes
and to unflag:
delete localStorage.f_active
if localStorage.f_active — doesn't pass (returned value is undefined)

Why "false" from Local Storage is "true" for the model? [duplicate]

I noticed that I cannot set boolean values in localStorage?
localStorage.setItem("item1", true);
alert(localStorage.getItem("item1") + " | " + (localStorage.getItem("item1") == true));
Always alerts true | false when I try to test localStorage.getItem("item1") == "true" it alerts true ... How can I set an item in localStorage to true?
Even if it's a string, I thought only === would check the type?
So
alert("true" == true); // should be true?
For the moment, all the implementations Safari, WebKit, Chrome, Firefox and IE, are following the current version of the WebStorage standard, where the value of the storage items can be only a string.
An option would be to use JSON parse and stringify method to serialize and deserialize the data, as I suggested some time ago in another question, for example:
var value = "true";
console.log(JSON.parse(value) === true); // true
Firefox's implementation of Storage can only store strings, but on 2009 September, W3C modified the draft to accept any data. The implementation (still) isn't caught up yet (see Edit below).
So in your case the boolean is converted to a string.
As for why "true" != true, as written in the description of Equal (==) in MDC*:
If the two operands are not of the same type, JavaScript converts the operands then applies strict comparison. If either operand is a number or a boolean, the operands are converted to numbers if possible; else if either operand is a string, the other operand is converted to a string if possible.
Note that the string is converted to a Number instead of a Boolean. Since "true" converted to a number is NaN, it will not be equal to anything, so false is returned.
(*: For the actual standard, see ECMA-262 §11.9.3 “The Abstract Equality Comparison Algorithm”)
Edit: The setItem interface was reverted to accept strings only on the 2011 Sept 1st draft to match the behavior of existing implementations, as none of the vendors are interested in supporting storing non-strings. See https://www.w3.org/Bugs/Public/show_bug.cgi?id=12111 for detail.
My solutions:
function tytPreGetBool(pre) {
return localStorage.getItem(pre) === 'true';
}
This is related to CMS’s answer.
Here’s a little function I’ve been using to handle the parsing part of this issue (the function will keep doing the Right Thing after the browser implementations catch up with the spec, so no need to remember to change out code later):
function parse(type) {
return typeof type == 'string' ? JSON.parse(type) : type;
}
I'd like to point out that it might be kinda easier just to wrap plain boolean value inside object and then, using JSON.stringify create local storage content and other way around, JSON.parse to retrive it:
let storeMe = {
myBool: true
}
localStorage.setItem('test', JSON.stringify(storeMe))
let result = JSON.parse(localStorage.getItem('test'))
Use store.js:
localStorage.setItem('isUser', true)
localStorage.getItem('isUser') === "true" //true
npm i -D store
↓
store.get('isUser') //true
What I usually do is just save the value in LocalStore as a Boolean, and then retrieve with a parsing method, just to be sure for all browsers. My method below is customized for my business logic. Sometimes I might store smth as 'no' and still need false in return
function toBoolean(str) {
if (typeof str === 'undefined' || str === null) {
return false;
} else if (typeof str === 'string') {
switch (str.toLowerCase()) {
case 'false':
case 'no':
case '0':
case "":
return false;
default:
return true;
}
} else if (typeof str === 'number') {
return str !== 0
}
else {return true;}
}
I'm not sure if LocalStorage can save boolean values but I can tell you that when you do alert("true" == true); it will never evaluate to true because you are implicitly comparing a string to a boolean. That is why to set boolean values you use true instead of "true".
eval can also be used carefully under some cases.
console.log(eval("true") === true) //true
When I need to store a flag I usually do:
localStorage.f_active = true (stored value is 'true' and it's fine)
if localStorage.f_active — passes
and to unflag:
delete localStorage.f_active
if localStorage.f_active — doesn't pass (returned value is undefined)

Why are these undefined variables not equal javascript?

Suppose I have the following event handler:
function handleCsvDump(e) {
console.log(e.currentTarget.getAttribute('download'));
e.currentTarget.download = undefined;
console.log(e.currentTarget.getAttribute('download'));
console.log(e.currentTarget.getAttribute('download') === undefined);
The information logged to the console when the corresponding button is clicked is:
mycsv.csv
undefined
false
Why is the last value false? Since e.currentTarget.getAttribute('download') is undefined, shouldn't it be true? If this is the wrong way to go about this, how can I test whether a variable is undefined?
You have to be careful when setting things this way, often things are expected to be strings, and if you set a value that isn't a string, it will first be coerced to a string, then assigned.
The download attribute is indeed a DOMString, meaning that anything you assign to it will first be coerced to a string if it isn't already, so when you assign undefined, it's actually first coerced to "undefined" and that is stored.
When you get it back out, and compare it to undefined, you're actually doing:
console.log("undefined" === undefined)
Hence getting false. If you do actually want to remove it, which is implied by wanting to set it to undefined (or null), you can instead use removeAttribute:
e.currentTarget.removeAttribute('download')

outputting content based on whether variable object equals "true"

I thought this would be straight forward after reading through w3c tutorials etc! But I appear to have something incorrect as the code doesn't output anything!
The variable is set based on whether the user is logged in or not:
var theJSON={"LOGGEDIN":false};
var theJSON={"LOGGEDIN":true};
I am then trying to show on the front end whether the user is logged in or not:
$(document).ready(function() {
if (typeof(theJSON[LOGGEDIN]) == true ) {
document.write ("Logged in")
} else {
document.write ("Not logged in");
}
i must be missing/mistyping something so simple?
There a couple of things wrong in your code:
When you try to access the LOGGEDIN property of the object, you are missing quotation marks. The expression theJSON[LOGGEDIN] will first try to get the value of the variable LOGGEDIN to use its value as property name. If such a variable does not exist (like it is in your example), the code will throw an error.
Now, The value of theJSON['LOGGEDIN'] is true and the type of the value is a boolean. typeof(theJSON['LOGGEDIN']) == true will never be true, because the typeof operator returns a string with the name of the data type, i.e. typeof(theJSON['LOGGEDIN]') will return "boolean".
If you just want to test whether the value is true, do:
if (theJSON['LOGGEDIN'])
w3schools is really not the best site to start learning about JavaScript, have a look at http://eloquentjavascript.net/ and the MDN JavaScript Guide instead.
if (typeof(theJSON["LOGGEDIN]") == true )
or
if (typeof(theJSON.LOGGEDIN) == true )
BTW, better use === instead of ==
if the value is number 1 it will still pass the condition.
Firstly, your theJSON is an actual object as given, not a JSON string. If it was you'd need to parse it as suggested.
The expression theJSON[LOGGEDIN] is incorrect syntax, you can either say theJSON.LOGGEDIN or theJSON["LOGGEDIN"]. And as this is a boolean, typeof(theJSON.LOGGEDIN) == "boolean".
The expression is a boolean, but it's value is true, so you can just write if (theJSON.LOGGEDIN).

Javascript IF loop takes false and execute the true loop with jquery

Here is jquery code in rails app. The purpose of the code is to eval the value of #rfq_need_report and show the #rfq_report_language if need_report is true or hide if false:
$(document).ready(function() {
var rpt = $('#rfq_need_report').val();
alert(rpt);
if (rpt) {
alert(rpt);
$('#rfq_report_language').show();
alert('show');
} else {
$('#rfq_report_language').hide();
alert(rpt);
alert('hide');
}
}); // end ready
The alert here is just for debug. The rpt is false, however alert('show') gets executed. It seems that the if loop is taking false and decided to execute the loop for true. Sometime If loop is working and sometime it does not. What could cause this strange behavior? Thanks.
In HTML the value field of any input like value="something" is always evaluated as a string. My guess is that in javascript you either set that value to true or false but it is in fact set as "true" or "false" as strings. You could try what was answered on this topic : How can I convert a string to boolean in JavaScript?
rpt could be a string, therefore converting it into a boolean will help:
if(rpt === "false") { rpt = false; } else { rpt = true; }
I have to assume that $('#rfq_need_report').val() is not passing back an actual boolean value, but something that JavaScript considers 'truthy', which is why your if statement executes the truth clause.
There are two quick methods (that I use) to convert 'truthy' values to an actual boolean:
1: var bool = !!truthy;
2: var bool = truthy === 'true'
I use the second when expecting a string value, and the first when not expecting a string.
The first example may need an explanation, so...
The first ! "nots" the truthy value to an actual boolean, albeit the opposite of what I wanted, the second "nots" it right back to where it should be.
For more examples of truthy vs falsy, simply pop javascript truthy falsy into your favorite search engine and start reading. My personal quick reference is: Truthy and falsy in JavaScript

Categories