Friday, July 29, 2011

All about function arguments

JavaScript allows a variable number of arguments to be passed into a function.  Thats actually a pretty cool feature that some languages (Java) have only added in the last few versions.  Lets look at it a little more by examining a function that takes two numbers and returns the sum:

function sum(firstNum, secondNum) {
return firstNum + secondNum;
}

We can call this function like this:

// Will return 14
sum(3, 11); 

But we are allowed to pass as many arguments to the function as we want:

// Will still return 14
sum(3, 11, 4, 99, 0, 2);

No errors are thrown, however the function only adds the first two numbers, as we coded it to do.  How can we take advantage of a variable number of arguments?  This is where the arguments object comes in.  It is available to you any time you are executing code within a function.  Its an array like object that contains each of the arguments that were passed to the current function.  Not just the declared parameters... but everything that was actually passed at call time.

Lets see how we can make our sum function work better using the arguments object:

function sum() {
var runningTotal = 0;
for (var i = 0; i < arguments.length; i++) {
runningTotal += arguments[i];
}
return runningTotal;
}

We now loop through each of the arguments adding them in turn.

// Will return 14
sum(3, 11);


// Will return 119
sum(3, 11, 4, 99, 0, 2);

So now that we can determine our arguments at call time, is there an easy way to find out (with code) how many declared parameters a function is expecting?  Yup.  Simply check the length property of the function.  Example:

function takesThree(x, y, z) {}
console.log(takesThree.length);
--> 3


function takesOne(first){}
console.log(takesOne.length);
--> 1

function takesNone(){}
console.log(takesNone.length);
--> 0


Friday, July 22, 2011

When do I use the === operator in JavaScript?

As new JavaScript programmers spend time with the language they often run into an operator they are unfamiliar with.  Most of us are familiar with the double equals (==) operator.  But what does the triple equals (===) operator, aka strict equals operator, do?  Why would we use it over ==?

Let me begin by explaining how the == operator works and then contrast the === operator.  Suppose I have the following code:
     var aNum = 3;
     var aStr = “3”;
     console.log(aNum == aStr);
     // output is true

Even though aNum is a number and aStr is a string… the variables are considered equal by the == operator.  This is because == will attempt to convert the variables to the same type before comparing them.  As long as you are aware that happens, it is usually OK, and sometimes helpful. 

Now let’s look at the same code with the === operator:
     var aNum = 3;
     var aStr = “3”;
     console.log(aNum === aStr);
     // output is false

The === operator makes no attempt to convert the variables before comparing, so of course the variables are not equal. 

To summarize, any time you are doing an equality comparison when variable type does matter, use the === operator.  If you don’t care what the variable’s type is, or specifically want type coercion, use the == operator.  

Saturday, July 16, 2011

How do I convert a String to a Number in JavaScript?

Variables in JavaScript are not strongly typed.  So if I have a variable named x:
       var x;

I can assign anything I want to it:
       X = 4; // legal
       X = “a string”;  // also legal
       X = {width: 45, height: 30};  // still legal

This can be nice at times… but if we aren't careful it can also introduce bugs.  For instance:
       var width = “3”;
       width += 7;
       // width now equals “37”, not 10

Cases like this require us to first convert the string to a number.  There are three methods of doing this which I will discuss:

  • The unary + operator
  • The global function parseInt()
  • The global function parseFloat()

If you know the string you are converting only represents a number (e.g. “3” or “5.9”, not “34px”) you can use the unary + operator.  Simply place a “+” right before string, and you now have a number.  Example:
       var width = “3”;
       var height = 9;
       var area = height * (+width);
       // area now equals 27

Note that you are not adding anything to the variable (that would be a binary operator), you are simply making it a number.  Again, this only works with a string that represents a number.  The following will give NaN (not a number):
       var width = +“5px”;
       // width now equals NaN

So, what to do with “5px”?  Do we have to remove the non-numeric characters first?  Nope.  The parseInt function helps us out here.  It will return an integer based on the first number it finds.  So the previous failure would now look like this:
       var width = parseInt(“5px”);
       // width now equals 5

The non-numeric characters after the number are ignored.  Note that non-numeric characters found before the number will cause a NaN to be returned.   Example:
       var width = parseInt(“w 5px”);
       // width now equals NaN

FYI, you can also pass a second parameter to the function which is the radix of the first argument.  Example:
       var x = parseInt("10010", 2);
       // x now equals 18

This works great, but what if we want a floating point number?  The global function parseFloat will do very similar work, returning a floating point number instead.  Example:
       var pi = parseFloat(“3.14”);
       // pi now equals 3.14

The same rules apply about having characters before and after as do to the parseInt function. 
       var pi = parseFloat(“3.14 degrees”);
       // pi now equals 3.14
       var pi = parseFloat(“x 3.14 degrees”);
       // pi now equals NaN

The parseFloat function can also take a string in scientific notation:
       var x = parseFloat("3.14e5");
       x now equals 314000

Finally a quick way of converting back to a String is as follows:
       var score = String(3722);
       // score now is a string of “3722”
       var label = “Your high score is “ + score;

As this demonstrates, conversion to a String is not needed as frequently because any time we add a string to a number… we get a string concatenation not a numeric addition. 

Bonus material:
There are two more global functions which may be helpful in some cases:
       isNaN()
       isFinite()

isNaN() will return true if the variable currently is NaN (not a number).  isFinite() will return false if the argument passed in is positive infinity, negative infinity, or NaN. 
   // will return true (because x is 3)
   isFinite(3 / 1);  
   // will return false (because x is positive infinity)
   isFinite(3 / 0);  
   // will return false
   isNaN(4);  
   // will still return false because
   // “4” can easily be converted to a number
   isNaN(“4”);  
   // will return true because the string can’t 
   // be easily converted to a number.
   isNaN(“4px”);  

Saturday, July 9, 2011

How do you make an object final in JavaScript?

­In Java, adding the final modifier to a class prevents the class from being extended.  C# has a similar keyword in sealed.  JavaScript, however, does not have a direct equivalent of this functionality... but its latest version does have some related capabilities. 

There are three functions which provide varying levels of control: 
  • Object.freeze(obj)
  • Object.seal(obj)
  • Object.preventExtensions(obj)

Passing an object into Object.freeze() will keep any new properties (or “methods”, which really are properties) from being added, no existing properties can be deleted, and the values of existing properties can’t be changed. 

Example:
  var x = {height:3, width: 4};
  Object.freeze(x);
  x.color = “red”; // may throw a TypeError exception
  delete(x.width);  // may throw a TypeError or return false
  x.height = 7;  // may throw a TypeError exception
  // x is still {height:3, width:4}



Object.seal() is similar in that no new properties can be added to the object, no existing properties can be deleted… but the values of existing data properties CAN be changed. 

Example:
  var x = {height:3, width: 4};
  Object.seal(x);
  x.color = “red”;  // may throw a TypeError exception
  delete(x.width);  // may throw a TypeError or return false
  x.height = 7;
  // x now is {height:7, width:4}



Finally the least restrictive function is Object.preventExtensions().  It will prevent any new properties from being added, but existing properties can be deleted or modified as normal. 

Example:
  var x = {height:3, width: 4};
  Object.preventExtensions(x);
  x.color = “red”;  // may throw a TypeError exception
  delete(x.width); 
  x.height = 7;
  // x now is {height:7}



These functions are new to the latest version of JavaScript, so they are only available in Firefox 4+, Chrome 6+, and IE 9+.  As of Safari 5 and Opera 11.5, the functions are not yet supported.