The CreatorCon Call for Content is officially open! Get started here.

Lukasz Bojara
Kilo Sage

Since I have started my journey into the ServiceNow's world I have seen, worked with and analysed a lot of code written by someone else than I. Analysing someone's code is a very useful exercise that can teach you a lot about coding in ServiceNow. At some point, I have noticed a pattern that is repeated over and over again not only by junior developers but also by very experienced people. I have even seen it in books about ServiceNow. And I am not saying that this is something that I wasn't doing because I was. At least to the time when I have spent a lot of time to debug my code and find out why even though I have checked it numerous times, it still does not work.


The pattern that I have on my mind is this:

var someValue = 'someValue';

if (someValue) {
   // do something
} else {
   // do something else
}

For sure most of you have seen it, and probably many are using it. What does it do? In few words: it checks if variable someValue exists. It is a very common pattern if you need to check that the value of the variable has been set. And in most cases, it does exactly what we expect. 

And this is the keyword: most cases

What does the if part of it does? The part if (someValue) will do exactly the same thing as if (someValue == true). And what does the == do? It tries to convert the values so that they will match types. So 1 == '1' is true, and more 1 == true also will give us true. By going this path 0 == false is also true. Probably you already see where I am going to. 

Part of my script was doing a calculation and the result of it was assigned to a variable, the case was that calculation run only on one condition, so then I had to be sure that variable has been set and if not I should skip part of my script. The issue was that on few cases where it should have run it was skipping. I have added few gs.log statemates to check the variable. What I notice is that the calculation resulted in 0. And now everything was clear, 0 means false so my if (x) in fact could look like this if (0) and if 0 == false then it meant that the code under if should be skipped.

I have done some searching on the web and also listened a few courses and yes, this is very specific but normal behaviour of JavaScript. This is one of the consequences of JavaScript being so "helpful" for us. In this case, it assumes that we have forgotten to do a conversion so it does is for us. This makes our code less predictable. 

If we will take this code:

var someValue = 1;

if(someValue) {
  gs.info('Good value =  ' + someValue);
  
} else {
	gs.error('Bad value =  ' + someValue);
}

The result will be:

find_real_file.png

But if we will change to 0, although the value has been set and we should have Good value = 0, we have Bad value = 0.

find_real_file.png

 

So what is the better way of checking if something exists and has been set?


Let's look at this code:

var someValue;

if(someValue) {
  gs.info('Good value =  ' + typeof someValue);
  
} else {
	gs.error('Bad value =  ' + typeof someValue);
}

This will be the result:

find_real_file.png

So in fact instead of doing if (x) we should check if x is undefined. This code below will always work if the value has been set, if the value has not been set and if the value is a number that equals 0.

This code:

var someValue = 0;

if(typeof someValue !== 'undefined') {
  gs.info('Good value =  ' + someValue);
  
} else {
	gs.error('Bad value =  ' + someValue);
}

Will result:

find_real_file.png

And if we will change var someValue = 0 to var someValue, the result will be:

find_real_file.png

 

Now we have a code that is doing what we want, ensures that variable has been set and is fully predictable.

This is a small detail, and in most cases, you will not have this problem. But there is this small percentage of cases where it will cause an issue, and we should always avoid the unpredictability of our code.

Comments
Khanna Ji
Tera Guru

If undefined comes, doesn't it throw error instead of control going to the else block? I think there should be a provision of using try-catch blocks in the script to handle the exceptions well. So you can add your code in try block if you are unsure of any error handlers and catch it in catch block;

try 
{
  Block of code to try
}
catch(err) 
{
  Block of code to handle errors
}
Lukasz Bojara
Kilo Sage

Thank you for your comment. I agree, the try...catch is a very good way of handling the undefined. But it will not always throw an error. 

If we will take this code:

try {
  
   gs.info('Some values = ' + someValue);

} catch (err) {
  
   gs.error(err.message);
  
}

 

It will go to catch and will result in ServiceNow:

find_real_file.png

 

But this code:

try {
   
   var someValue;

   gs.info('Some values = ' + someValue);

} catch (err) {
  
   gs.error(err.message);
  
}

Will not throw an error in ServiceNow and the result will be:

find_real_file.png

And this is this small percentage of cases that I mentioned 🙂

 

P.S. I had also an occasion to develop for a client where try...catch was not allowed to be used in scripts. 

DScroggins
Kilo Sage

Nice article!

 

You can also use gs.nil() to determine if the object is null, undefined, or an empty string like so:

var someValue = 0;

if(!gs.nil(someValue)) {
  gs.info('Good value =  ' + someValue);
  
} else {
  gs.error('Bad value =  ' + someValue);
}
Lukasz Bojara
Kilo Sage

Thanks David. gs.nil() works perfectly on server side, but when you need to check it on client side than unfortunatelly you can not use it. But for sure this solution is a very good alternative 🙂

Serghei Tolstov
Tera Contributor

Good article, i had similar issue but i had no control of the field so i didn't know what values a field could bring, number, string or any nullified values  (undefined, NaN, null) so my solution was :

 

 

function test(x){
if (x==0 || x){
//operate on x
}else{
//act on nullified value
}


(in this case == instead of ===,  as i would check if  it is number and parce it to int later in a code)

 

Version history
Last update:
‎10-21-2019 09:23 AM
Updated by: