Top 10 JavaScript traps for a C# developer
If you are an experienced C# developer, coming into JavaScript world for application development, you will end up making few common mistakes. However some of the mistakes you would make are due to the basic differences between any strongly typed language [C#, Java etc.] and a dynamically typed language [JavaScript, Python etc]. Although dynamic feature was added to C# version 4.0, its initial design was based on static typing.
Note, I am primarily a .Net developer and have experience of developing web applications using JavaScript, and I admit that I made these mistakes when I started learning JavaScript. I spent good amount of time analyzing the root cause of the issues, just to realize that some of the mistakes were really due to my experience in C# language and assumption that JavaScript code would work exactly. I was wrong however. So in this article, I will cover top 10 JavaScript traps for a C# developer so that they don’t make the same mistakes which I did.
I assume that you have basic experience with C# language, so that we can focus more on JavaScript language in this article. With that, let’s jump into the traps.
1. Equality Operator
Most common trap between the two languages is the equality operator, also known as comparison operator. Unlike C# which has one equality operator [==], JavaScript has two [== and ===].
Let’s take a look at equality operator in C# first.
For predefined value types in C#, equality operator returns true if the values of its operands are equal, otherwise it returns false. Assuming you have basic understanding of C# language, below code snippet should be easy to understand.
Console.WriteLine("10 == 10 ? " + (10 == 10)); // returns true Console.WriteLine("10 != 10 ? " + (10 != 10)); // returns false. Console.WriteLine("10 != 20 ? " + (10 != 20)); // returns true.
For reference types other than string, equality operator returns true if its
two operands refer to the same object.
In the code snippet below,
emp1
and emp2
are two different Employee
instances, hence comparing two different instances in such case would return a
false value.
var emp1 = new Employee(); var emp2 = new Employee(); Console.WriteLine("emp1 == emp2 ? " + (emp1 == emp2)); // returns false
In below code snippet, however, we have assigned emp2
instance
variable to emp1
, so both the instances are now pointing to same
memory location. So comparing two instance in such case would return a true
result.
emp1 = emp2; Console.WriteLine("emp1 == emp2 ? " + (emp1 == emp2)); // returns true
For the string type, == compares the values of the strings. In the code snippet below, strings “A” and “B” are not same, comparing these two strings would return a false result.
Console.WriteLine("A == B ? " + ("A" == "B")); // returns false
In below code snippet, we have copied string “A” to temp
variable and compared it with “A” string constant. Since both the strings
contains same value, comparison in such case would return a true value.
var temp = string.Copy("A"); Console.WriteLine("A == A ? " + ("A" == temp));
In JavaScript however, equality operator works differently. Let’s understand the difference in these two equality operators first.
Equals (==) If the two operands are of same datatype, equality operator returns true if operand values are same, false otherwise.
console.log(‘10 == 10 ? ‘ + (10 == 10)); // returns true console.log(‘"10" == "10" ? ‘ + ("10" == "10")); // returns true console.log(‘true == true" ? ‘ + (true == true)); // returns true
If the two operands are NOT of the same datatype, JavaScript converts the operands and then applies comparison. If either operand is a number or a boolean or a string, the operands are converted to numbers if possible.
In below code snippets, string value “10″, boolean value ‘true’ and ‘false’ gets converted into a number before the comparison takes place. All the comparison statement below returns a true value.
console.log(‘10 == "10" ? ‘ + (10 == "10")); console.log(‘1 == true ? ‘ + (1 == true)); console.log(‘0 == false ? ‘ + (0 == false)); console.log(‘0 == "" ? ‘ + (0 == "")); console.log(‘0 == " " ? ‘ + (0 == " "));
If both operands are objects, then JavaScript compares internal references which are equal when operands refer to the same object in memory.
var x = { name: ‘Prasad‘ }; var y = { name: ‘Prasad‘ }; var z = x; console.log(x == y); // returns false console.log(x == z); // returns true
Strict Equal (===) Returns true if the operands are strictly equal with no type conversion.
In below code snippet, both the operands are of same data type with same value, all the comparison statements would return true result.
console.log(‘10 === 10 ? ‘ + (10 === 10)); console.log(‘"20" === "20" ? ‘ + ("20" === "20")); console.log(‘true === true ? ‘ + (true === true));
Below code statement would return false result since the data type of the operands are different.
console.log(‘10 === "10" ? ‘ + (10 === "10")); console.log(‘10 === "20" ? ‘ + (10 === "20")); console.log(‘1 === true ? ‘ + (1 === true)); console.log(‘0 === false ? ‘ + (0 === false)); console.log(‘0 === "" ? ‘ + (0 === "")); console.log(‘0 === " " ? ‘ + (0 === " ")); console.log(‘"" === " " ? ‘ + ("" === " "));
2. Variable Scope
C# allows programmer to declare a variable at different locations, which determines its scope. Variables that are defined at the class level are available to any non-static method within the class. Variables declared within a method’s code block are available for use by any other part of the method, including nested code blocks. And finally, if you declare a variable within a block construct such as an If statement, that variable’s scope is only until the end of the block.
In the code listing below variable favoriteCity
is declared at
class level, so it is accessible to all the methods in the class
VariableScope
. Considering its a static variable, it can be
accessed inside a static or an instance method, however it wont be accessible
using a class instance.
Variables declared at class level can be overridden in the functions. In
below example, Main
method overrides variable
favoriteCity
and sets it to “New York”. Since the class level
variable is accessible to all the methods, PrintFavoriteCity
function can access it. Any local variable declared in Main
method
or PrintFavoriteCity
won’t be accessible outside method
definition.
Finally, we have declared a welcomeMessage
variable inside a
if block. The scope of this variable is only within the if
block and it wont be accessible outside the block, within Main
method or PrintFavoriteCity
method.
class VariableScope { private static string favoriteCity = "London"; static void Main() { Console.WriteLine("Your favorite city is {0}", favoriteCity); favoriteCity = "New York"; PrintFavoriteCity(); if (favoriteCity.Equals("New York")) { var welcomeMessage = "Welcome New Yorker"; Console.WriteLine(welcomeMessage); } } static void PrintFavoriteCity() { Console.WriteLine("Your favorite city is {0}", favoriteCity); } }
JavaScript has two scopes: global and local. A variable that is declared outside a function definition is a global variable, and its value is accessible and modifiable throughout your program. A variable that is declared inside a function definition is local. It is created and destroyed every time the function is executed, and it cannot be accessed by any code outside the function. JavaScript does not support block scope.
In the code listing below, favoriteCity
variable is declared
outside function definition, hence its scoped as global and can be accessed
inside any function. Variable favoriteIndianCity
is declared inside
PrintFavoriteCity
function, so its a local scope variable and
cannot be accessed outside function definition. Finally we have declared a
welcomeMessage
variable inside an if block. Since
JavaScript does not support block scoped variable, welcomeMessage
variable can be accessed anywhere within the containing function.
var favoriteCity = "London"; function PrintFavoriteCity() { console.log(favoriteCity); var favoriteIndianCity = "Pune"; console.log(favoriteIndianCity); if (true) { var welcomeMessage = "Hello dear traveler!"; console.log(welcomeMessage); } welcomeMessage = "Hello dear traveler, welcome back! "; console.log(welcomeMessage); }
3. For each
In C# foreach statement is used to repeat a group of embedded statements for each element in an array or a collection which implements IEnumerable or IEnumerable<T> interface. Most of the collection classes in C# like Array, List, Dictionary, HashSet etc implement these interfaces, so iterating over these collection using foreach statement is a common practice.
Iterating over string array collection
var rainbowColors = new[] { "Red", "Orange", "Yellow", "Green", "Blue", "Indigo", "Violet" }; foreach (var rainbowColor in rainbowColors) { Console.WriteLine(rainbowColor); }
Iterating over specialized collection – StringCollection
var cities = new StringCollection { "Pune", "London", "New York", "Mumbai" }; foreach (var city in cities) { Console.WriteLine(city); }
Iterating over Generic collection – List
var weekdays = new List(){"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"}; foreach (var weekday in weekdays) { Console.WriteLine(weekday); }
Unlike C#, JavaScript has three flavors of for each statements!.
for each…in : It is used to iterate a specified variable over all values of object’s properties. For each distinct property, a specified statement is executed. However, for each…in is deprecated as the part of ECMA-357 (E4X) standard. E4X support has been removed, but for each…in will not be disabled and removed because of backward compatibility considerations.
var sum = 0; var obj = {prop1: 10, prop2: 20, prop3: 30}; for each (var item in obj) { sum += item; } print(sum); // prints "60", which is 10+20+30
for…in : It is used to iterates over property names in arbitrary order. Since the order is not consistent, this version should not be used to iterate over array elements.
let arr = [ 3, 5, 7 ]; arr.foo = "hello"; for (let i in arr) { console.log(i); // logs "0", "1", "2", "hello" }
for…of : It is used to iterates over property values in consistent order. This version is suitable to iterate over array like elements, however this feature is yet to be implemented in all the browsers and is part of ECMA6 proposal.
let arr = [ 3, 5, 7 ]; arr.foo = "hello"; for (let i of arr) { console.log(i); // logs "3", "5", "7" }
4. Switch statement
In C#, the switch statement is a control statement that selects a switch section to execute from a list of candidates. Each switch section contains one or more case labels followed by one or more statements.
The following example shows a simple switch statement that has five switch sections. Each switch section has one case label, such as case 10, case 20 etc. Each case label specifies a constant value. The switch statement transfers control to the switch section whose case label matches the value of the switch expression. If no case label contains a matching value, control is transferred to the default section, if there is one. If there is no default section, no action is taken and control is transferred outside the switch statement.
Console.WriteLine("Enter your age"); var age = int.Parse(Console.ReadLine()); switch (age) { case 10: Console.WriteLine("Drink milk"); break; case 20: case 30: Console.WriteLine("Take Latte or beer"); break; case 50 - 10: Console.WriteLine("You can have Whiskey"); break; case 50: Console.WriteLine("Take medicine"); break; default: Console.WriteLine("Invalid input"); break; }
JavaScript is a dynamically typed language. In other words, language doesn’t enforce you to declare the type during variable declarations and you can easily change the data type later. As we discussed earlier, in regular if statement comparison, data type doesn’t matter unless you are using strict comparison that specifically check for data type.
y = 5; x = ‘5‘; if(x == y){ console.log("they‘re the same"); // logs ‘they‘re the same‘ }
The exception is case values in the switch statement. For the case to be a match, the data types must match. Think for it as switch statements including === (strict equal) instead of == (equal) for case comparisons.
y = 5; switch(y){ case ‘5‘: console.log("y is 5"); // this won‘t log the message }
However, main difference in JavaScript switch statement is that, each section
can contain an expression or a constant. Note, C# language accepts only constant
value in switch expression. Below JavaScript code snippet demonstrates case
expression. Note the switch(true)
statement, which always execute
in this case and the actual value of input
is used in case
expression.
var input = prompt("enter your age"); switch (true) { case input > "10" && input < 20: console.log(‘Take Milk‘); break; case input > "21" && input <= 40: console.log("Take Beer"); break; case input >= 41 && input <=50 : console.log("Take Whiskey"); break; case input > 51: console.log("Take Medicine"); break; default: console.log("Invalid input"); break; }
5. Function overloading
In C#, function overloading is, when you have two or more methods with the same name but different signatures. At compile time, the compiler works out which one it’s going to call, based on the compile time types of the arguments and the target of the method call.
In below code snippet, we have two forms of Add
function and
depending on the type and number of arguments, appropriate Add
function gets called.
static void Main() { Console.WriteLine("10 + 20 = " + Add(10,20)); Console.WriteLine("10 + 20 + 30 = " + Add(10, 20, 30)); Console.ReadLine(); } static int Add(int number1, int number2) { return number1 + number2; } static int Add(int number1, int number2, int number3) { return number1 + number2 + number3; }
JavaScript does not support function overloading!! Even though everything in JavaScript is an Object in itself, the language does not support some of the common object oriented language feature like function overloading.
So what happens if you declare two functions with the same name? Lets see it in action.
In the code block defined below, we have declared two Add
functions which takes different number of parameters. JavaScript unfortunately
overrides the Add
function defined earlier using 2 parameters with
the Add
function defined later using 3 parameters, so for a calling
application only one Add
function is available.
So the question is, what happens when we call Add
function with
2 arguments, when its signature contains three arguments. Well, in above case,
parameter num3
gets initialized to undefined
, which is
our next trap in the list!
6. undefined function parameter
In C#, once you define a function with a given number of parameters, the
calling code has to pass same number of arguments, unless any of the parameters
are set as optional. For example, WelcomeUser
function define in
below code takes two parameters – userName
and
welcomeMessage
.
static void WelcomeUser(string userName, string welcomeMessage = "Welcome") { Console.WriteLine("{0} {1}!", welcomeMessage, userName); }
The welcomeMessage
parameter was declared as an optional
parameter, so the calling code may not necessarily pass its value, in which case
its default value ‘Welcome’ will be considered during function execution. If the
calling code passes welcomeMessage
argument, it will override its
default value while calling the function.
static void Main(string[] args) { WelcomeUser("Prasad"); WelcomeUser("Colin", "Good Morning"); // WelcomeUser(); // this won‘t compile as userName is mandatory parameter }
JavaScript however works in a different manner. It does not enforce user to
pass values for all the parameters during function call. In such case, a
variable that has not been assigned a value is of type
undefined
.
Let’s take a look at the example. WelcomeUser
function defined
below takes two parameters userName
and
welcomeMessage
. In the first call, we are passing arguments ‘Scott’
and ‘Good Morning’ to WelComeUser
function, and it logs it as
expected. No surprises here.
Now, when we call the function without passing same number of arguments,
JavaScript treats that argument as undefined. So in second call, when
we pass ‘Prasad’ as an usreName
argument,
welcomeMessage
gets initialized to undefined, so it displays the
output as ‘Prasad undefined!’
Similarly, when we call the function without passing any arguments, both the
parameters gets initialized to undefined
and it displays the output
as ‘undefined undefined!’
function WelcomeUser(userName, welcomeMessage) { console.log(userName + " " + welcomeMessage + "!"); } WelcomeUser("Scott", "Good Morning"); WelcomeUser("Prasad"); WelcomeUser();
Point to note that, unlike C# compiler, JavaScript compiler wont display any
compile time error for undefined parameters. So now the question is how to
handle undefined parameters? You can use undefined
and the strict
equality and inequality operators to determine whether a variable has a value or
not. So let’s modify above code to do the same.
function WelcomeUser(userName, welcomeMessage) { if (userName === undefined) { userName = "Admin"; } if (welcomeMessage == undefined) { welcomeMessage = "Welcome"; } console.log(userName + " " + welcomeMessage + "!"); }
As you can easily notice, in the above code snippet, we have set
userName
to ‘Admin’ and welcomeMessage
to ‘Welcome’,
if calling code doesn’t pass the argument value.
7. Truthy and Falsy
In C#, true and false values are always represented by a boolean variable or an boolean expression. The controlling conditional expression of an if-statement is a boolean-expression, which must return either true or false. If the condition doesn’t return a boolean value, a compile time error occurs. Let’s look into the code now.
The displayFlag
boolean variable is initialized to true, so the
statement enclosed in if block will always execute and outputs “Display
flag is true”.
bool displayFlag = true; if (displayFlag) { Console.WriteLine("Display flag is true"); }
Below code block shows simplest example of boolean expression, which must return either true or false value [True in this case].
if (2 > 1) { Console.WriteLine("2 is greater than 1"); }
As we discussed in the earlier sections, C# is a statically typed language, so the operands in a boolean expression should be compatiable for equality operation. For e.g. comparing a int variable with a string would result into a compile time error as shown in below example.
var firstNumber = 10; var secondNumber = "10"; if (firstNumber == secondNumber) { } // compile time error
To ensure the controlling conditional expression of an if-statement return a boolean-expression, we need to typecast the if statement as shown below
var firstNumber = 10; var secondNumber = "10"; var equalNumber = ((bool)(firstNumber.ToString() == secondNumber));
In JavaScript, 0, false, ”, undefined, null, NaN are falsy values. All other value are truthy.
if (!0) { console.log("0 is falsy"); } if (!false) { console.log("false is falsy"); } if (!‘‘) { console.log("‘‘ is falsy"); } if (undefined) { console.log(‘undefined is falsy‘); } if (!null) { console.log(‘null is falsy‘); } if (!0/0) { console.log(‘NaN is falsy‘); }
Note that, a space character [‘ ‘] is a trythy value in JavaScript, and so does the Infinity.
if (1 / 0) { console.log(‘Infinity is truthy‘); } if (‘ ‘) { console.log("‘ ‘ is truthy"); }
8. Curly braces and return statement
Both C# and JavaScript languages provides a return statement to return the execution control to the caller, however there is one subtle gotcha when you used it along with curly braces in JavaScript.
You will find endless arguments on web on ‘whether the curly brace should appear on the same line as block construct [class, function etc.] or whether they should appear on their own line’. In C#, it doesn’t matter really. It’s a person preference to have it on the same line or new line, however I would suggest you to choose one and stick to it.
Add
function defined in below code listing contains curly braces
on new line, while the GetDefaultCategory
function contains opening
curly brace and return statement on different lines, which C# compiler will
happily compile.
public static int Add(int num1, int num2) { return num1 + num2; } public static dynamic GetDefaultCategory(){ return new { Name = "General" }; }
JavaScript however behaves differently in this case. The Add
function is similar to C# version and will always display the addition of two
numbers passed in. However GetDefaultCategory
function defined
below will simply return the call to the caller without returning the object
literal. This is due to automatic semicolon insertion feature
of JavaScript. In this case, since we have opening curly brace on the next line
after return statement, JavaScript compiler will insert a semicolon after return
statement causing it to exit from the function without returning any value.
function Add(num1, num2) { return num1 + num2; } function GetDefaultCategory() { return { name: "General" } };
This can easily get more difficult as compiler doesn’t return any error in this case, however caller will get a null reference rather than the object literal. To avoid such kind of situation, always use curly brace on the same line as return statement or block construct, as shown below
function Add(num1, num2){ return num1 + num2; } function GetDefaultCategory() { return { name: "General" } };
9. this keyword
The this
keyword in C# is generally used for two purposes
- Access the current instance of the class
- To add extension methods on existing types without creating new types.
Let’s discuss both of these options in detail
Following code listing contains an Employee
class with two
properties which has been protected by private setters, so only the
parameterized constructor can initialize these values. Note that the constructor
uses this.Id
syntax to access the property on a given instance.
Similarly, overridden ToString
method retrieves class properties
using this
keyword.
public sealed class Employee { public int Id { get; private set; } public string Name { get; private set; } public Employee(int id, string name) { this.Id = id; this.Name = name; } public override string ToString() { return string.Format("ID : {0} , Name : {1}", this.Id, this.Name); } }
C# 3 introduced ‘Extension Method’ concept in the language. Extension methods
enable you to “add” methods to existing types without creating a new derived
type, recompiling, or otherwise modifying the original type. This includes even
adding extension method on sealed type like string
or
Employee
class defined in earlier code listing. Below code listing
adds an extension method PrintNameAndLength
to Employee class. Note
the this
keyword used in the PrintNameAndLength
signature, which denotes extension method on Employee
type.
public static class EmployeeExtension { public static string PrintNameAndLength(this Employee emp) { return emp.Name + " : " + emp.Name.Length; } }
Once declared, you can invoke it as a normal instance method as shown in below code example
var emp = new Employee(1, "Prasad"); Console.WriteLine(emp.PrintNameAndLength());
The most common extension methods are the LINQ standard query operators that
add query functionality to the existing
System.Collections.IEnumerable
and
System.Collections.Generic.IEnumerable
types.
10. Hoisting
As we examined in earlier sections, JavaScript supports only function level scope as compared to C# which has different scope rules [class, method, block]. However, it’s worth to find out how JavaScript handles the scoping.
In JavaScript, all the variable declared inside a function share same scope. Behind the scene, JavaScript hoists all the variable declaration to the top of the function and initialize them to undefined. Their assignment still remain on the same line where it was declared. This process is known as ‘Variable Hoisting’.
Let’s take a look at simple JavaScript function defined below.
function doSomething() { console.log(someVariable); //undefined var someVariable = 100; console.log(someVariable); // 100 if (true){ someVariable = 200; console.log(someVariable); // 100 } }
JavaScript hoist the variable someVariable
to the top of the
function doSomething>
and initialize it to
undefined
. Below is the code definition after the hoisting is done.
Since variable was gets hoisted to the top of the function, it can be accessed
from anywhere inside the function. This is the main reason why JavaScript does
not support block scoping.
function doSomething() { var someVariable = undefined; console.log(someVariable); //undefined someVariable = 100; console.log(someVariable); // 100 if (true){ someVariable = 200; console.log(someVariable); // 100 } }
And then JavaScript does function hoisting as well! However, the hoisting rules for variable and functions are different. JavaScript provides two ways to define a function in a program – Function Expression and Function Statement. The easiest way to tell them apart is, if it starts with the function keyword, then it is a function statement.
try { printOne(); printTwo(); } catch (e) { console.log(e.message); } // Function Expression var printOne = function () { console.log("One"); } // Function Statement function printTwo() { console.log("Two"); }
During function hoisting process, function statement is transformed behind the scenes into a function expression and then both the variable and the assignment are hoisted to the top of the function scope. So the function gets converted as shown below
var printOne = undefined, printTwo = undefined; printTwo = function(){ console.log("Two"); } try { printOne(); printTwo(); } catch (e) { console.log(e.message); } printOne = function () { console.log("One"); }
Note that, function expression follows same rule as variable hoisting, but function statement behaves differently.
Summary
Ah!, we did it. Here comes the summary I hope this post helped you to understand basic differences between JavaScript and C# languages, and common traps associated with it.
Please provide your feedback in the comments section below
source: http://www.codetails.com/2014/05/27/top-10-javascript-traps-for-a-c-developer/