18

Is there a better way to improve the below statement to check if the val() is 'true' or 'false' and if it is then it will change it to a Boolean. The reason being, some of the values may be a word.

var thisval = $(this).val();
if (thisval == "true"){
    ao[id] = true;
} else if (thisval == "false"){
    ao[id] = false;
} else {
    ao[id] = $(this).val();
}
ngplayground
  • 20,365
  • 36
  • 94
  • 173
  • 2
    possible duplicate of [How can I convert a string to boolean in JavaScript?](http://stackoverflow.com/questions/263965/how-can-i-convert-a-string-to-boolean-in-javascript) – KevSheedy Nov 11 '13 at 13:31
  • Whats wrong with this code? All answers so far, in my opinion, are less readable. Extract into a function (accepting a string, returning a boolean or string) and never worry about it again. – Caramiriel Jan 08 '19 at 09:58

10 Answers10

25

Most readable:

var thisval = $(this).val();
ao[id] = thisval === 'true' ? true : 
         thisval === 'false' ? false : 
         thisval;

One-liner based on the conditional operator:

var thisval = $(this).val();
ao[id] = thisval === 'true' ? true : (thisval === 'false' ? false : thisval);

One-liner based on || and && behavior:

var thisval = $(this).val();
ao[id] = thisval === 'true' || (thisval !== 'false') && thisval || false;

Shortest one-liner (combination of the above):

var thisval = $(this).val();
ao[id] = thisval === 'true' || (thisval === 'false' ? false : thisval);
Tibos
  • 27,507
  • 4
  • 50
  • 64
  • Third solution is the best to me because, even in a case where we don't know for sure that ```thisval``` is a string , at the end, if not equal to ```true``` or ```false```, we can assume ```thisval``` is probably already a **Boolean** and if it's not it wont pass further test anyway. – svassr Feb 07 '14 at 20:39
  • @svassr All 3 solutions behave the same (give exactly the same output for any input). The only difference is in what JS operators are used. I believe that with the proper optimizations they might even result in the same bytecode. – Tibos Feb 07 '14 at 21:50
  • Right indeed. I understood that, I was just confused because I was reading 3 posts on the topic at the same time :p – svassr Feb 10 '14 at 15:06
  • @Gaspa79 The code is equivalent to that of the OP - values other than 'true' and 'false' are returned as they are. The conditional operator does not enforce anything about the type of the result. Run the code in the console to convince yourself :D. – Tibos Nov 29 '16 at 16:48
  • @Tibos I stand corrected. The ? operator doesn't work the same way it does in strongly typed languages it seems. I did well in giving you +1 before. Thanks. – Gaspa79 Nov 29 '16 at 20:06
11

Try JSON.parse().

"true" and "false" are actually json representations of true, false. This is how ajax parses json object as a string from server side. If on server side, we return true, false => the browser will receive it as a string "true" or "false" (json representation)

if ( $(this).val() == "true" ||  $(this).val() == "false") {
    ao[id] = JSON.parse($(this).val());
}else {
    ao[id] = $(this).val();
}

DEMO

Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • Using JSON just for parsing something you know can only be either `"true"` or `"false"`sounds like quite an overkill... also, the `.val()` method wil be called three times every time the code above is called. – Haroldo_OK Nov 29 '16 at 16:56
  • 1
    @Haroldo_OK: I don't think it's overkill, that's also something we use when we parse response from server. – Khanh TO Dec 01 '16 at 13:27
  • this also works for numbers, eg. JSON.parse('123') // returns 123 – Alex Feb 11 '22 at 21:23
3
String.prototype.bool = function() {
    return (/^true$/i).test(this);
};


if ( $(this).val() == "true" ||  $(this).val() == "false") {
    ao[id] = $(this).val().bool();
}else {
    ao[id] = $(this).val();
}
Ankit Tyagi
  • 2,381
  • 10
  • 19
1

This might be slightly more elegant:

var thisval = $(this).val();

if (thisval === "true" || thisval === "false") {
    thisval = (thisval === "true");
}
Strille
  • 5,741
  • 2
  • 26
  • 40
1
('' + thisval).toLowerCase() === 'true'

May be useful if extra string and toLower is negligible - may be simple.

Its true if its explicitly set to true, (boolean or case insensitive string) and false otherwise.

 // so complete solution to get the same value if neither true nor false
const thisvalStr = ('' + thisval).toLowerCase();
a[id] = thisvalStr === 'true'? true: (thisvalStr === 'false')? false: thisval;

Can be modified to include additional values like, 1, etc as per need by using || or an array.

const TrueValuesStr = ['1', 'true']

TrueValueStr.contains(('' + thisval).toLowerCase() === 'true')
msanjay
  • 2,255
  • 2
  • 19
  • 19
0
var thisval = $(this).val();

switch(thisval) { 
case 'true' : 
    ao[id] = true; 
    break; 

case 'false' : 
    ao[id] = false; 
    break; 

default: 
    ao[id] = thisval; 

}

I would create an array to hold the two possible values for when the string is true or false. Then, I would search to see if thisval is found inside that array. If it is not, the indexOf function will return -1. Afterwards, it is just a matter of going over those values and build up the cases that you want.

EDIT: I have updated the code based on the suggestion of Tibos. Thank you!

vladzam
  • 5,462
  • 6
  • 30
  • 36
  • 1
    The OP did ask for a way to improve his code, where is the improvement? – Mark Walters Nov 11 '13 at 13:34
  • Usually, when there are more than 2 if statements, switch shows better performance. That is the only thing I kept in mind when providing my answer. I thought that by 'improved way' the asker meant performance management :) – vladzam Nov 11 '13 at 13:36
  • The improvement in performance for this would be minimal and not noticeable. Caching his `$(this).val()` would be useful in any case, but this code just seems more longwinded in my opinion. – Mark Walters Nov 11 '13 at 13:42
  • Indexof negates all the performance benefit from going to a switch instead of two ifs. Why not `switch(thisval) { case 'true' : ao[id] = true; break; case 'false' : ao[id] = false; break; default: ao[id] = thisval; }`? – Tibos Nov 11 '13 at 13:45
  • You are right, Tibos! That would be faster indeed! I will update the code accordingly. – vladzam Nov 11 '13 at 13:49
0

I'd prob prefer

const parseMaybeBool = val =>
  typeof val === 'string'
    ? val.toLowerCase() === 'true' || val.toLowerCase() === 'false'
      ? Boolean(val)
      : val
    : val;

or w/ types

const isBool = (val: unknown): val is boolean =>
  typeof val === 'boolean' ||
  (typeof val === 'string' &&
    (val.toLowerCase() === 'true' || val.toLowerCase() === 'false'));

const parseMaybeBool = (val: unknown) =>
  isBool(val) ? Boolean(val) : val;

colemars
  • 979
  • 3
  • 12
  • 25
0

In the pleasant summer of 2022, here's how I'd do it:

const thisval = $(this).val();

ao[id] = ['true', 'false'].includes(thisval) ? JSON.parse(thisval) : thisval;

You could also go a step further and have it handle numbers too:

ao[id] = ['true', 'false'].includes(thisval) || !Number.isNaN(Number(thisval))
  ? JSON.parse(thisval)
  : thisval;
ffxsam
  • 26,428
  • 32
  • 94
  • 144
0

You can do all of this in one line if you want to:

const getBool = value => value == "true" || value == "false" ? value == "true" : value;

getBool($(this).val());

Explanation

In JavaScript you'll probably be used to using something like

if(answer == "yes"){ ...

answer == "yes" will evaluate to true or false.

For your question, this can certainly help one part of it. If there were only "true" or "false" options it would be as simple as:

const getBool = (value) => value == "true"
getBool("true"); // true
getBool("false"); // false

We can now wrap this in a ternary operator, basic overview:

`if this` ? `then do this` : `if not, then do this`

So we check if the value is true or false, and if so use the above technique.

value == "true" || value == "false" 

If its not, we can just return the value without any modifications. So the test becomes:

value == "true" || value == "false" ? value == "true" : value;
Djave
  • 8,595
  • 8
  • 70
  • 124
-1

In nodejs by using node-boolify we can use isBoolean() & Boolify()

Validation Results

var isBoolean = require('node-boolify').isBoolean;

isBoolean(true); //true
isBoolean('true'); //true
isBoolean('TRUE'); //false
isBoolean(1); //true
isBoolean(2); //false
isBoolean(false); //true
isBoolean('false'); //true
isBoolean('FALSE'); //false
isBoolean(0); //true
isBoolean(null); //false
isBoolean(undefined); //false
isBoolean(); //false
isBoolean(''); //false

Boolean Conversion Results

var Boolify = require('node-boolify').Boolify;

Boolify(true); //true
Boolify('true'); //true
Boolify('TRUE'); //null
Boolify(1); //true
Boolify(2); //null
Boolify(false); //false
Boolify('false'); //false
Boolify('FALSE'); //null
Boolify(0); //false
Boolify(null); //null
Boolify(undefined); //null
Boolify(); //null
Boolify(''); //null
Ratan Uday Kumar
  • 5,738
  • 6
  • 35
  • 54