Checking for an Existing, Nonempty String - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript Checking for an Existing, Nonempty String - Supercoders | Web Development and Design | Tutorial for Java, PHP, HTML, Javascript

Breaking

Post Top Ad

Post Top Ad

Saturday, December 22, 2018

Checking for an Existing, Nonempty String

Checking for an Existing, Nonempty String



Problem

You want to verify that a variable is defined, is a string, and is not empty. 

Solution

The simplest solution when testing for a nonempty string is the following:

if (typeof unknownVariable === 'string' && unknownVariable.length > 0) 

If the variable isn’t a string, the test will fail, and if the string’s length isn’t longer than zero (0), it will fail. 

However, if you’re interested in testing for a string, regardless of whether it’s a String object or a string literal, you’ll need a different typeof test, as well as test to ensure the variable isn’t null:


if (((typeof unknownVariable != 'undefined' && 
unknownVariable) &&
 unknownVariable.length() > 0) &&
typeof unknownVariable.valueOf() == 'string') ...
 

EXPLAIN


You can use length to find out how long the string is and test whether the string variable is an empty string (zero length):

if (strFromFormElement.length == 0) // testing for empty string
 

However, when you’re working with strings and aren’t sure whether they’re set or not, you can’t just check their length, as you’ll get an undefined JavaScript error if the variable has never been set (or even declared). You have to combine the length test with another test for existence and this brings us to the typeof operator. 

The JavaScript typeof operator returns the type of a variable. The list of possible re‐ turned values are:

• number if the variable is a number 
• string if the variable is a string 
• boolean if the variable is a Boolean 
• function if the variable is a function 
• object if the variable is null, an array, or another JavaScript object
• undefined if the variable is undefined 

Combining the test for a string and a test on the string length ensures our app knows if the variable is a non-zero length string or not:

if (typeof unknownVariable == 'string' && unknownVariable.length > 0) ... 

However, if you’re looking for a nonempty string regardless of whether the string is a literal or an object, than things get a little more interesting. A string that’s created using the String constructor:

var str = new String('test');

has a typeof value equal to object not string. We need a more sophisticated test. First, we need a way to test whether a variable has been defined and isn’t null. The typeof can be used to ensure the variable isn’t undefined:


if (typeof unknownVariable != 'undefined')...

But it’s not sufficient, because null variables have a typeof value equal to object. So the defined and not null test is changed to check to see if the variable is defined and isn’t null:


if (typeof unknownVariable != 'undefined' && unknownVariable) ... 


Just listing the variable is sufficient to test whether it’s null or not. We still don’t know, though, if the variable is a nonempty string. We’ll return the length test, which should allow us to test whether the variable is a string, and is not empty:
if ((typeof unknownVariable != 'undefined' && unknownVariable) &&
 unknownVariable.length > 0) ...

If the variable is a number, the test fails because a number doesn’t have a length. The String object and string literal variables succeed, because both support length. However, an array also succeeds, because the Array object also supports length. To finish the test, turn to a little used method, valueOf(). 

The valueOf() method is available on all JavaScript objects, and returns the primitive (unwrapped) value of the object. For Number, String, and Boolean, valueOf() returns the primitive value. So if the variable is a String object, valueOf() returns a string literal. If the variable is already a string literal, applying the valueOf() method temporarily wraps it in a String object, which means the valueOf() method will still return a string literal. 

Our finished test then becomes:

if(((typeof unknownVariable != "undefined" &&  unknownVariable) && 
 (typeof unknownVariable.valueOf() == "string")) && 

Now, the test functions without throwing an error regardless of the value and type of the unknown variable, and only succeeds with a nonempty string, regardless of whether the string is a string object or literal.

The process is complex, and normally your application usually won’t have to be this extensive when testing a value. You’ll typically only need to test whether a variable has been set (typeof returns the correct data type), or find the length of a string in order to ensure it’s not an empty string.

 Loose and Strict Equality Operators

I used loose equality (== and !=) in this section, but I use strict equality (=== and !==) elsewhere in the book. My use of both types of operators is not a typo. Some folks (Douglas Crockford being the most outspoken) consider the loose equality operators (== and !=) to be evil, and discourage their use. The main reason many de‐ velopers eschew loose equality operators is that they test primitive values rather than the variable object, in totality, and the results of the test can be unexpected.

For instance, the following code succeeds:

var str1 = new String('test'); 

if (str1 == 'test') { ...}



whereas this code fails:
var str1 = new String('test'); 

if (str1 === 'test') { ...}

The first code snippet succeeds because the string literal (test) and the primitive value the str1 variable contains are identical. The second code snippet fails the conditional test because the objects being compared are not equivalent, though they both share the same primitive value (test): the str1 variable is a String object, while the compared value is a string literal.

While results of this comparison are relatively intuitive, others are less so. In the fol‐ lowing code snippet, a string is compared to a number, and the results may be unexpected:

var num = 0; 

var str = '0';



console.log(num == str); // true 

console.log(num === str); // false
In the Abstract Equality Comparison Algorithm, when a string is compared to a number, the loose equality comparison is treated as if the following occurs:

console.log(num === toNumber(str));
 

And therein lies the risk of loose equality: not understanding the implicit type conversion. 

Sometimes, though, the very nature of the loose equality operator can be useful. For instance, the following code snippet demonstrates how the loose equality operator saves us time and code. The test to see if the variable is “bad” succeeds with standard equality regardless of whether the variable is undefined or null, where it wouldn’t succeed if strict equality had been used:


var str1;
if (str1 == null) {
 console.log('bad variable'); 
}

Rather than using the first typeof in the solution, I could shorten the test to the following and get the same result:

if ((unknownVariable != null &&
unknownVariable.length > 0) && 
 typeof unknownVariable.valueOf() == 'string') ... 

Should you always use strict equality except in these rare instances? Just to ensure you don’t get unexpected results? 

I’m going to buck the industry trend and say “No.” As long as you’re cognizant of how the equality operators work, and your code is such that you’re either only interested in primitive values or you want the object type coercion I just demonstrated, you can use loose equality operators in addition to strict equality.

 Consider the following scenario: in a function, you’re testing to see if a counter is a certain value (100, for example). You’re expecting the counter, passed into the function, to be a number, but the developer who sent the value to your function passed it as a string. 

When you perform the test, you are only interested in the value of the variable, not whether it’s a string or number. In this case, strict equality would fail, but not because the value isn’t what you’re testing for, but because the tested value and the function argument are different types. And the failure may be such that the developer using your function thinks that the application generating the value is in error, not that a type conversion hasn’t been made. 

You don’t care in your function that the variable is a string and not a number. In this case, what you’re implicitly doing is converting the variable to what you expect and then doing the comparison. The following are equivalent:

if (counter == 100) ... 
if (parseInt(counter) === 100) ...

In a more realistic scenario, you may be working with a string, and you don’t care if the person who passed the string value to your function used a String constructor to create the string, or used a string literal—all you care about is the primitive value:

var str = 'test'; 
var str2 = new String('test'); 
doSomething(str);
doSomething(str2); 
... 
function doSomething (passedString) { 
if (passedString == 'test')
 ... 


No comments:

Post a Comment

Post Top Ad