Blog

How Good C# Habits can Encourage Bad JavaScript Habits: Part 2 – False-y, Testing and Default Values, Comparisons, and Looping

This is the second post in a multi-part series covering common mistakes C# developers tend to make when they first start writing JavaScript.

The first post covered the following topics:

  • 1. Having Variables & Functions in Global Scope
  • 2. Not Declaring Arrays & Objects Correctly

Introduction

This post continues to focus on areas where C# developers tend to make poor decisions when writing JavaScript based on their previous training. The languages are syntactically similar enough that C# developers tend to not invest the time to learn JavaScript’s differences.

The following post points out several misunderstandings that can get you into some confusing situations.

More Bad Practices

3. Not Understanding False-y Values

Unlike C# there are many values that JavaScript has that act false-y. Inside an if statement truth-y values will proceed into the then branch and false-y values will drop into the else branch. It is important to understand these special false-y values not only when writing your code, but when trying to understand other people’s code.

The False-y values are:

false
null
undefined
"" (empty string)
0
NaN (not a number)

All other values that aren’t listed in the above list will be considered truth-y (including all objects, the strings “0”, “false”, and many other strange combinations).

Best Practice

When it comes to understanding the outcome of a logical statement, you should know the false-y values in JavaScript. Since these rules are considerably different than C#, you should take the time to understand them.

We will examine the implications of knowing these false-y values a little further in the next few sections.

4. Not Testing & Setting Default Values Correctly

You can easily spot a C# developer if you see them checking for null inside of an if statement or when setting a default value.

Checking for Null

It is common and considered a best practice in C# to check for null before using a variable. If you don’t, then you might fall victim to the dreaded “Object reference not set to an instance of an object” exception. Also, when dealing with strings you’ll also want to test if it is empty or not. The following code snippet is a typical way to do this in C#.

// C# example. Don't do this in JavaScript
if ( someString != null &&
    someString.length > 0 ) {
    //Do something here...
}

In fact, the above code snippet is such a common practice that there is a special IsNullOrEmpty method in the .NET framework to help simplify this case.

// C# code to simplify checking for null and empty string
if ( !string.IsNullOrEmpty(someString) ) {
    //Do something here...
}

As it turns out, when considering the JavaScript false-y values, you can shorten all this logic to the following code snippet. The following code snippets checks to see if the variable is not undefined, not null, and is not empty.

// Simplified JavaScript syntax to check for
// undefined, null, & empty string values
if ( someString ) {
    //Do something here...
}

As a side note, the above someString variable is more likely to be undefined than it is null due to variable hoisting, but thanks to false-y values that is being checked.

Setting A Default Value

Another common scenario you’ll run into is setting a default value to a variable. In C#, you might be be tempted to write some code like the following.

// C# example. Don't do this in JavaScript
if ( someString == null ) {
   someString = "default Value";
}

// Slightly better, but don't do this either
someString = someString ? someString : "default value";

Instead, there is a much simpler way to perform this in JavaScript that uses the logic or operator.

// JavaScript syntax to set a default value
someString = someString || "default value";

Best Practice

Based on the false-y rules we learned earlier, if we want to check if a variable is undefined, not null, and has a value then all we need to do is check the object itself.

5. Using the Wrong Comparison Operators

Knowing that JavaScript is loosely typed and having the False-y values fresh in our mind from the previous section, let’s focus now on common mistakes when using the comparison operator.

Coming from C# you will intuitively use the == and != in your if statements, however, this may yield some results that you didn’t expect.

Problems When Using == or != Comparison Operators

When using the == and != comparison operators, JavaScript tries to help you by coercing the two values into the same type so that it can compare them. This sounds like a good idea, but in the end it can lead to some very confusing results. Check out the following for some of these unexpected results.

// Unexpected Comparisons using the == Operator
0          ==  ''        //true
0          ==  '0'       //true
false      ==  '0'       //true
null       ==  undefined //true
' trn ' ==  0         //true

You Should Use the === or !== Instead

A better way to compare is to use the === and !== operators (also known at the identify operators), which are much more rigorous. They will not only check the value, but also check the type as well. The results of these comparisons are probably more what you would expect in a strongly typed language. The following code uses the same comparison as the above example, but uses the identify operator instead.

// Expected Comparisons using the === Operator
0          === ''        //false
0          === '0'       //false
false      === '0'       //false
null       === undefined //false
' trn ' === 0         //false

Best Practice

When you are comparing two values in JavaScript you should use the Identify Comparison Operators (=== & !==).

6. Not Using the for…in Statement Correctly

For those of you who regularly write C#, you probably don’t use the classic for loop much, but use the for…in loop instead. If you aren’t careful this can byte you in several different ways.

Using the for…in Statement on Arrays

You may see the for…in statement used to iterate over arrays, but don’t! You can get into some weird issues. You should instead use the for statement when looping over arrays.

The for…in statement does not guarantee the order of the items that are going to be retrieved, plus you can get into some interesting problems.

In the following example we are creating an array and then setting the 5th index with a value of “test”. Since we have an item at the 5th index, the array is marked as having a length of 6 items. So far, there shouldn’t be any surprises here.

var myArray = [], name;
myArray[5] = "test";
console.log( myArray.length ); //6

However, if you used the for..in statement on this array, you would only see the one item that you inserted in the array, which is probably not what you intended. If this is what you intended, then you should probably not be using an array and should be using an object instead.

var myArray = [], name;
myArray[5] = "test";
console.log( myArray.length ); //6

for ( name in myArray ) {
    console.log( name, myArray[name] );
    //Outputs...
    //   5, test
}

You can execute and modify the above code from

jsFiddle.

You should use the standard for loop when iterating over an array. The following example does loop over the entire range of indexes, although most of them are undefined since we didn’t set their values.

var myArray = [], name;
myArray[5] = "test";
console.log( myArray.length ); //6

for ( var i = 0, length = myArray.length; i < length; i++ ) {
    console.log( i, myArray[i] );
    //Outputs...
    //   0, undefined
    //   1, undefined
    //   2, undefined
    //   3, undefined
    //   4, undefined
    //   5, test
}

You can execute and modify the above code from

jsFiddle.

If you are not convinced, there is another problem that you can run into when using the for…in statement on an array. Now just suppose that you or some other library changed the prototype of the Array object? If someone where to add a property to the Array.prototype it would also show up as one of the keys in the for…in.

var myArray = [], name;
myArray[5] = "test";
console.log( myArray.length ); //6

Array.prototype.someVariable = "Where did this come from?";
for ( name in myArray ) {
    console.log( name, myArray[name] );
    //Outputs...
    //   5, test
    //   someVariable, Where did this come from?
}

You can execute and modify the above code from

jsFiddle.

This actually brings up our next subtopic about using the for…in statement correctly when using an object.

Using the For…In Statement Incorrectly with Objects

As we discussed briefly in the above section, hopefully you are only using the for…in statement with objects and not arrays. You might have seen the for…in used like the following

for ( var name in object ) {
    //Your code here
}

That seems harmless, right? And in many cases it does exactly what you want it to. As it turns out, you should be careful using the above syntax. The for…in statement will actually iterate through all the properties of the object and also the properties that are inherited from the prototype! Since you probably don’t want to iterate over your inherited prototype properties, you should check the object you are enumerating to see if it contains the property before proceeding.

Your modified code snippet should look something like the following instead.

/* Check if object has property before
iterating, because functions inherited
from prototype are also included */
for ( var name in object ) {
   if ( object.hasOwnProperty(name) ) {
      //Your code here
   }
}

The following code snippet shows an example of when the for…in statement might show some undesired results.

var Person = function( firstName, lastName ) {
  this.firstName = firstName;
  this.lastName = lastName;
  return this;
};

Person.prototype = {
  isMarried : false,
  hasKids: false
};

var john = new Person( "John", "Smith" ),
  linda = new Person( "Linda", "Davis" ),
  name;

john.isMarried = true;

console.log( "Not Checking hasOwnProperty" );
for ( name in john ) {
  console.log( name + ": " + john[name] );
  //Outputs
  //  firstName: John
  //  lastName: Smith
  //  isMarried: true
  //  hasKids: false
}

console.log( "Checking hasOwnProperty" );
for ( name in linda ) {
  if ( linda.hasOwnProperty(name) ) {
    console.log( name + ": " + linda[name] );
    //Outputs
    //  firstName: Linda
    //  lastName: Davis
  }
}

You can execute and modify the above code from jsFiddle.

In the above code we created two Person objects and set it’s prototype to include two new properties (“isMarried” and “hasKids”). We then loop over the properties of the “john” person, you will see that not only are his firstName and lastName displayed, but also the inherited “isMarried” and “hasKids” prototype values! In contrast, by checking .hasOwnProperty() when looping over linda’s properties, we only see that her immediate properties are displayed, instead of displaying her inherited properties as well.

Best Practice

The take aways for this point are:
* Use the for statement for arrays
* Use the for…in statement when iterating over objects and check the hasOwnProperty method

Conclusion

This article has covered some of the common issues you might address coming from C# to JavaScript. I have committed just about everyone of the above Bad Practices myself when I starting to code in JavaScript heavily.

With the recent serge of jQuery hitting the market and other great JavaScript libraries, it is important that we as developers understand the language instead of just thinking that our previous language knowledge will get us by.

This article only covers some of the things you should know. The next post in the series will be published next week. In the meantime please feel free to add comments of any other gotchas that you’ve experience coming from a C# background. I would love to hear about it.

Tweet about this on TwitterShare on FacebookShare on RedditShare on Google+Share on LinkedIn

  • http://twitter.com/Poetro Peter Galiba

    There is no !=== operator in JavaScript. You wrote too much = signs.

  • http://www.stevefenton.co.uk Steve Fenton

    I think you have a typo, when you describe the “!===” operator, which I think should just be “!==”

  • http://www.facebook.com/andris.reinman Andris Reinman

    Great article! One sidenote though – you can't always use

    if(someString) { … }

    to check for undefined values. If you use this in the global context and the variable is undefined then it would throw a ReferenceError. Use if(window.someString) instead or declare always your variables with “var”.

  • amWirick

    Thanks for catching the typo! post updated.

  • http://fr.linkedin.com/in/morgautalexandre Alexandre Morgaut

    I would warn about this habit to set default value this way -> someString = someString || “foo”;
    because with this statement, the empty string will always be overridden which is not often exactly what we what. a good example -> function createBox(width, height, margin) { margin = margin || 2; … (margin will never be settable to 0)

  • Dean Landolt

    Definitely don't use window.someString. If you're unsure if someString has been defined you can do a typeof someString !== “undefined” to be sure.

  • http://rushfrisby.myopenid.com/ Rush Frisby

    someString = someString ? someString : “default value”;

    simpler still

    someString = someString ?? “default value”;

  • http://www.facebook.com/obi.kenobi Rodrigo Obi-Wan Iloro

    is it only me, or doing:

    someString = someString || “default value”;

    and

    if(!someString) { //do something }

    fails miserably on IE7. Looks like cross browser support is out of the question, at least with “falsy” optimizations.

  • http://twitter.com/tbassetto Thomas Bassetto

    I cite: “The take aways for this point are: * Use the for statement for arrays * Use the for…in statement when iterating over objects and check the hasOwnProperty method”

    The list is not formatted ;)

  • http://twitter.com/matthias_k Matthias

    I often see code like this:

    if (my.var == undefined) { //… }

    This works … most of the time, although comments already discouraged its use. Did anybody ever try the following?

    var undefined = true;

    Suddenly the comparison null == undefined will not work anymore.

    In my understanding, undefined is not a JavaScript keyword. You can try this on jsFiddle: http://jsfiddle.net/LDPCd/

  • http://trycatchfail.com/ Matt Honeycutt

    I would definitely not call code like the following a best practice in JavaScript:

    someString = someString || “default value”

    I think that's actually a common mistake C# devs in switching to JavaScript. Often you don't want to overwrite a “false-y” value with a default, as the false-y value is the intended value. Instead, you should explicitly check if the variable is null or undefined. I was bitten by code exactly like that numerous times while building liteGrid.

  • http://dan.cx/ Daniel15

    Instead of using a normal “for” loop to iterate through an array, you can also use the forEach method:

    [1, 2, 3, 4, 5].forEach(function(item)

    {

    alert(item);

    });

    See https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Array/forEach for more details (and a function to implement it for browsers that don't implement JavaScript 1.6, like IE6).

  • Brunis

    Strange you compare it to csharp and talk about javascript like you could use any of this in a microsoft environment..

  • http://mo.notono.us/ Oskar

    You may want to mention the performance reason for the for loop format, where you declare the length variable. Its another point not normally considered when coming from C#.

  • martinp

    Which is why you should always use the Self-Executing Anonymous Function described in part 1. ;-)

  • martin

    Great work and great timing Elijah.

    My experience with JS is a little unusual as I learned and have used it for several years in TestComplete. So, not only is my experience until recently devoid of the DOM, I also was forced into MS JScript (which, amongst other things, doesn't allow var x = {};, always needed 'new').

    I am right now taking my first steps into using Javascript in a browser environment and using JQuery. Your articles are like gold!

    Many thanks,
    Martin

  • Pingback: JavaScript global namespaces « Kiss' world

  • http://jasonbunting.com/ Jason Bunting

    “…that's actually a common mistake C# devs [make] in switching to JavaScript.”

    Um, I don't think so – both you and the author of this blog post got it wrong.

    He's wrong because he implies that there was a decisive decision to make that syntax “the” syntax for setting default values (“// JavaScript syntax to set a default value”) – that only exists in his imagination – this wasn't the intent of || and besides that, as I think someone else pointed out in the comments, we may not always want to set a variable to a “default value” based on whether or not the same variable or another is falsy. In fact, the author's own example, that he tells you not to do in JavaScript, is actually completely valid! I refer to the example where someString is tested for a null value – that specificity may be exactly what we want to test for.

    Just because null and the empty string are both falsy doesn't mean we want to set a variable to some default value for both cases. Maybe, again as someone else here mentioned, the empty string is a valid value. But what if null isn't a valid value? I would want code that looked exactly like the code the author tells us not to use in JavaScript. THAT'S ABSURD!!!

    Anent your comments regarding this syntax, it isn't a mistake to use that syntax for setting default values if the author of code using it expects certain values out of the parameters passed to it. In other words, what if I do want to overwrite any falsy value with a non-falsy one? Or, better yet, I want to homogenize the falsy value to a specific, falsy value? The following code is completely valid and, in certain situations, actually useful:

    someVariable = (someVariable || false);

    So, the better answer/response to all of this is that it just depends. That's the problem with “best practice” rhetoric – too many people read the words “best practice” as “this is the only way to do this, you are an idiot if you do it any other way.” Completely ridiculous, but the author of these blog posts apparently thinks this way, considering his dogmatic “don't do this in JavaScript” comments throughout.

  • Pingback: István Miklós Antal » Web developer’s guide

  • Pingback: Good C# Habits, Bad JavaScript Habits | ChurchCode

  • Jason Dielman

    Great post Mike!

  • Jason Dielman

    Great post Mike!

  • Jason Dielman

    What I think the author is getting at is that there are methods and conventions in C# that don’t directly translate into JavaScript. JavaScript is a very dynamic language and the author is eluding to other conventions of JavaScript in comparison to a strongly typed language such as C# or Java (no connection to JavaScript).

    True, checking for null or some other false-y value might be exactly what the developer is looking for depending upon the project and the expected data set with which the code is interacting. However, those who’ve not had a lot of exposure to JavaScript may encounter unexpected results if they don’t take the authors concepts into consideration.

  • Jason Dielman

    What I think the author is getting at is that there are methods and conventions in C# that don’t directly translate into JavaScript. JavaScript is a very dynamic language and the author is eluding to other conventions of JavaScript in comparison to a strongly typed language such as C# or Java (no connection to JavaScript).

    True, checking for null or some other false-y value might be exactly what the developer is looking for depending upon the project and the expected data set with which the code is interacting. However, those who’ve not had a lot of exposure to JavaScript may encounter unexpected results if they don’t take the authors concepts into consideration.