Home > JavaScript > Getting started with JavaScript with a C# background

Getting started with JavaScript with a C# background

Over the past few years, I have worked with a number of developers new to Web Development and JavaScript and I have noticed that most people seam to stumble at the same places and make the same mistakes that I did when first moving into JavaScript development. I believe most of the confusion comes from moving from a strongly typed language such as VB.NET or C# to the flexibility of a dynamic language such as JavaScript.

In this post I will try to explain some of the basic concepts and approaches used in JavaScript development that may not seam as obvious to someone first starting out.

For a quick easy way to follow the examples in this post I recommend jsfiddle.net.

 

1. Scope

I can say without a doubt, the most commonly misunderstood concept of JavaScript by new developers is Scope. Scope in JavaScript works very different than scope in C#. Unfortunately to explain how JavaScript Scope works I first need to cover a few other items. We will revisit Scope a little later.

 

2. Types
JavaScript there are only 5 primitive types: boolean, string, number, null and undefined. Anything else we come across is an object. (including functions but we will get to that later…)

The JavaScript boolean and string types behave very similarly to their C# counter parts. There are some minor differences, but I wont go into those here.

The other types however are a little bit more interesting.

The JavaScript number type for instance represents a 64-bit floating-point double. JavaScript has no float, int, double or any other types to represent numbers. The other interesting point is the 2 valid number values NaN and Infinity. The value NaN (stands for Not a Number) occurs when a value is returned as a number type, but the value is not parseable as a number. This is usually when trying to parse a non numeric string value (such as "abc") to a number. The value infinity occurs when a number exceeds the upper limit of the floating point numbers, which is 1.7976931348623157E+10308.

The JavaScript null type is similar to the C# Null however it does have one gotcha. When applying the typeof operator to a null value, it will return "object". This is actually completely wrong, and is a mistake that was made very early in the language’s standardisation.

The JavaScript undefined type is similar to null, however while null means a variable or property has no value, undefined means that the variable or property does not exist. For a variable it can also mean that the variable was declared but never assigned a value. This concept may be strange when first starting to work with JavaScript as usually a compiler would complain if a variable or property used when it didn’t exist. Because JavaScript is a dynamic language and the differences between different browsers, these cases are common and a defensive approach needs to be taken when you are not sure a variable or property is going to exist at runtime. (see the Truthy and Falsey section for how to check for the existence of a variable or property)

var foo;
console.log(typeof foo); // undefined

foo = 123;
console.log(typeof foo); // number

foo = "abc";
console.log(typeof foo); // string

foo = true;
console.log(typeof foo); // boolean

foo = null;
console.log(typeof foo); // object

foo = {};
console.log(typeof foo); // object

As you can see the variable foo was declared without assigning a value. At this point in time the type of foo is undefined. The same variable foo is then reused and assigned multiple values. As each value is assigned, the type of the variable changed to the type of its value.

Update:
For completeness I will also add the function type. While not a primitive type, performing a typeof on a function object will return the sting ‘function’. Function objects are explained further in the Functions are objects section.

foo = function() {};
console.log(typeof foo); // function

 

3. Truthy and Falsey

While JavaScript has a bool type, due to the magic or coercion we just saw in the types section, these are not the only types that can be evaluated in a true or false manner. Enter Truthy and Falsey.

In JavaScript any object can be automatically coerced into a boolean representation (i.e. true or false). I had a number of goes at simplifying my explanation of this and eventual got it down to one sentence:

Anything that exists and has a value will evaluate as true unless the value is false, null, undefined, 0, NaN or an empty string.

var foo;

if(foo) // exists but is undefined -> evaluate as false
{
    console.log(foo); // will not execute
}

foo = "Hello World";

if(foo) // exists and has a value -> evaluate as true
{
    console.log(foo); // will execute    
}

In this example, If the variable is undefined, the condition evaluates as false. If the variable exists, but has a value of 0, the condition again evaluates as false. It’s only if the variable has been declared and assigned a truthy value that the if block would be entered.

We can now use these concepts to write defensive JavaScript, by ensuring variables or properties exist before using them. This is also a common approach for feature detection.

if (someObject && !someObject.foo){
    someObject.foo = 'foo';
}

console.log(someObject.foo); 

The above code checks if someObject is truthy (not null etc) and if someObject.foo has been defined. If someObject.foo has not been defined it will set it to the string value ‘foo’ before continuing to log it out.

 

4. Functions are objects

Now this is the tricky one. A function in JavaScript is an object just like any other object. While this concept might not be as huge a deal for someone familiar with Generics and Lambda expressions, it is still a big difference between C# and JavaScript.

You can create anonymous functions, assign a function to a variable, pass that variable to another function, change the function object to do other things, parse it as a string and many more weird and wonderful things.

This should look familiar. Define a function called foo and then call the named function.

function foo(){ 
    console.log('bar');
}

foo();  // bar

But how about this?

var foo = function (){ 
    console.log('bar');
}

foo();  // bar

In the second example, we defined an anonymous function and assigned to to the variable foo.

We now have a variable foo which we can do what we please with.

console.log(foo); // function (){ 
                  //     console.log('bar');
                  // }

foo.randomProperty = "We just added a property to an object";

console.log(foo.randomProperty); // We just added a property to an object

These few things are but a scratch on the surface of what can be done, so you can see a function object is very flexible.

 

5. Hoisting

When JavaScript is executed, the interpreter moves or “hoists” all variable declarations to the top of their containing function / scope boundary, regardless of where they occur. Take the below code for example.

var foo = 'global foo';

function myFunction() {
    console.log(foo);
}

myFunction();

This code defines a global variable foo and sets its value to ‘global foo’. We then call my function that logs the value of foo. Now lets change this function so that it logs the global variable and then logs a local version of foo;

var foo = 'global foo';

function myFunction() {
    console.log(foo); // undefined
    var foo = 'local foo';
    console.log(foo); // local foo
}

myFunction();

Why does the first console.log return undefined? What has happened is the redefinition of foo has been hoisted to the sounding scope boundary. The code that is actually being executed after hoisting has occurred looks like this.

var foo = 'global foo';

function myFunction() {
    var foo;
    console.log(foo); // undefined
    foo = 'local foo';
    console.log(foo); // local foo
}

myFunction();

As you can see, at runtime the re-declaration of foo has been defined but not assigned, thus the first console.log is correctly logging undefined.

 

6. Scope Revisited

OK. Time to talk about Scope.

In C#, scope is introduced by braces or are "Block Scoped". A variable declared inside a class, function, loop, condition block, etc are available to all members within the blocks braces. That being the case we should all agree that the below C# code will write 0 1 2 3 4 5

 public void Method1()
 {
  var elements = new int[] { 0, 1, 2, 3, 4, 5 }; // available everywhere in the function

  for (var i = 0; i < elements.Length; i++)
     {
        var element = elements[i]; // available only within this for loop
          Console.Write(element);
     }
 }

In JavaScript however, functions define scope. A variable declared outside of a function is in the global namespace. As in any language, you should try to avoid polluting the global namespace. A variable declared in a function is visible anywhere inside that function, and because of hoisting this is the case regardless of where it is defined. Variables defined within a function are not visible outside the function. This sounds a lot simpler than it is and the best way to explain is with examples.

Here is the JavaScript version of the above code.

function Method1(){
var elements = [0, 1, 2, 3, 4, 5]; // available everywhere in the function
         

for(var i = 0; i < elements.length; i++) {
  var element = elements[i]; // remember Hoisting? will be available everywhere, even though it was originally declared inside the for loop
  console.log(element);
}
}

Again executing the code will produce 0 1 2 3 4 5.

As we covered in the Functions section, a function can be treated like any other object, including being added to an array. We will now take the the array of values and create an array of functions that return the original values.


function Method1(){
var elements = [0, 1, 2, 3, 4, 5],
    functions= [];

for(var i = 0; i < elements.length; i++) {
  var element = elements[i]; // remember Hoisting?
  functions.push(function() {
      console.log(element);
    });
}

functions[3]();
}

The above code again iterates through the elements array, but this time adds an element to the functions array which is an anonymous function to log the corresponding value from the elements array. The last line of the above snippet addresses the object in the 3rd position of the functions array (functions[3]) and then executes it as a function (();).

Still with me?

Achievement Unlocked JavaScript Padawan

 

If you have got your mind around that, now take a guess at what value would be logged by the execution of this function. The C# developer in you will be thinking it should log 3. If that is the case, the C# developer in you would be wrong. Its actually 5…

As discussed before, JavaScript does not have "Block Scope" thus the for loop has not introduced new scope. This means that each time the element variable is accessed, the same memory location is updated, rather than a loop iteration specific variable as one would expect in C#. So when the loop has finished, the variable ‘element’ has the value of 5.

To correct this we need to introduce a function to create scope around our variable reference. For ease of explanation we will first just wrap our for block in an anonymous, auto executing function, (often referred to a closure) and pass the element parameter into this function.


function Method1(){
var elements = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],
    i,
    functions= [];

for (i = 0; i < elements.length; i++) {

    (function (element) {                    // start of closure

        functions.push(
            function() {
                console.log(element);
            });
        
    }(elements[i]));                         // end of closure
}

functions[3]();
}

We now log 3 as originally expected.The code is now similar to the C# example as the element variable is declared, assigned used and destroyed within the for loop. This is because Hoisting moves variables to the top of a function, the closure stops it bubbling up to the same location as the other variable declarations.

 

7. Namespacing Patterns

In C# we rely heavily on namespacing to group together like functionality and avoid collisions with other objects or variables in the global namespace.

As JavaScript has no concept of a class, there is also no concept of namespacing in the form you are used to. We can however use what we have just learned by using objects, functions and closure scope to achieve a similar effect.

I am not going to go into details on the different approaches to namespacing within JavaScript, because I stumbled across this post by Addy Osmani (@addyosmani) that covers it much better and in more detail than I ever could. http://addyosmani.com/blog/essential-js-namespacing/

 

8. Conclusion

There is a whole lot more to the language than what I have described here but I hope this post will help some people making the transition to JavaScript avoid some of the common misunderstands that can cause frustrations in the early days.

 

About these ads
Categories: JavaScript Tags:
  1. November 8, 2011 at 10:39 pm | #1

    nice post.
    Also check out this js tutorial http://nathansjslessons.appspot.com/lesson?id=1000

  2. November 30, 2011 at 10:01 pm | #2

    A very good post. Isn’t there a “function” type now?

  3. November 30, 2011 at 10:41 pm | #3

    Performing a typeof against a function object will return ‘function’ however I don’t believe this is an actual primitive type as such. I could be wrong though.

    Ill do a bit of research and update the post accordingly.

  4. January 17, 2013 at 4:33 am | #4

    dude this is an extremely helpful post. Moving from C# to JavaScript is a painful transition but this post definitely is helping me to bridge the gap. Now that TypeScript is out I’m hoping to avoid JavaScript altogether but I figured it’s still good to have a thorough understanding of it. BTW, love the tag line in the header – Mo Knowledge Mo Problems – hilarious and so true!

    • January 17, 2013 at 6:35 am | #5

      Glad to hear you are making the transition.

      I will just offer one bit of reading before you jump on the TypeScript language.

      http://webreflection.blogspot.de/2012/10/javascript-made-everyone-crazy.html?m=1

      I believe a lot of these new languages that compile / transpile to JavaScript are just adding another layer of sugar and syntax and introduces a new set of quirks and gotchas to be learned.

      • January 28, 2013 at 4:37 am | #6

        just got around to reading the article. Yeah all of his points are valid but I still can’t bite the javascript bullet. I’ve just been doing C# for too long (preceded by several years of VB before .Net came along). If JavaScript were more like Dart I would be all over it with no complaints. But JavaScript is just a different animal and rather than try to undo 17 years of OO/Typed wiring in my brain I’d rather just succumb to the old-man-get-off-my-lawn persona and wag my finger at all of you JavaScript guys :-)

  1. March 22, 2012 at 11:44 pm | #1

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 319 other followers

%d bloggers like this: