Javascript Gotchas listed to help avoid mistakes
A gotcha in programming is something unexpected although a documented feature of a computer system and not a bug. These gotchas throw beginners off Javascript programming and send some people running and screaming. In my opinion, Javascript is one of the most widespread languages as it is available on all browsers but one of the least learned languages. Let’s start with basic ones.
1. Floating point arithmetic
This can be a major cause of frustration for people who are new to Javascript and are trying to perform some kind of mathematical computation.
<br /><br /> <script><br /><br /> alert(0.02 / 0.1); //0.19999999999999998 <br /><br /> alert(1.14 * 100); //113.99999999999999 ;)<br /><br /> </script><br /><br />
This is where the Math.round() functions come in handy
2. Plus operator overloading
The plus operator stands for both arithmetic operations and also string concatenation. This is convenient if used correctly. Lets take a look
<br /><br /> <script><br /><br /> var msg, one="1";<br /><br /> msg = 2 + "1"; // msg = "21"<br /><br /> msg = 2 + one; // msg = "21"<br /><br /> msg = 1 + 1 + 1 + " musketeers"; // msg = "3 musketeers"<br /><br /> msg = "Bond " + 0 + 0 + 7; //msg = "Bond 007" <br /><br /> </script><br /><br />
The above behaviour is because the operations are performed left to right. If we use parantheses the behaviour will change based on the order of the string or number in it.
3. Semicolon insertion at line feed
Javascript automatically inserts ; at a line feed. Lets see this in action with a simple example:
<br /><br /> <script><br /><br /> function returnSame(a){<br /><br /> return //Inserts semi-colon to convert to return;<br /><br /> a //a becomes a; - Unreachable<br /><br /> }<br /><br /> alert(returnSame(2)); //Output is undefined<br /><br /> </script><br /><br />
The magical semicolon insertion can get things complicated while creating objects using object literals
4. typeof operator
typeof is a unary operator. The results are not one would normally expect. It suprisingly evaluates null to “object”.
<br /><br /> <script><br /><br /> var obj={}; //object created using object literal<br /><br /> var arr=[]; //array created by array literal<br /><br /> alert(typeof(obj)); //object - Good<br /><br /> alert(typeof(arr)); //object - Bad<br /><br /> alert(typeof(null)); //object - Ugly! ;)<br /><br /> </script><br /><br />
It should only be used to distingush objects from other primitive types.
5. false, null, undefined, NaN, Infinity
They stand for different things although they might look similar or at times look redundant. Javascript uses three primitive datatypes numbers, strings and boolean. In addition it has two trivial datatypes undefined and null. Both null and undefined are equal according to the equality operator (==)
<br /><br /> <script><br /><br /> var a;<br /><br /> alert (a); //undefined<br /><br /> alert (1/0); //Infinity<br /><br /> alert (0/0); //NaN<br /><br /> 0/0 == 0/0; //false - a NaN != NaN<br /><br /> alert (b); //error<br /><br /> </script><br /><br />
6. String replace only replaces first occurence
Unlike PHP or other languages, string replace in Javascript only replaces the first occurence of a string by default.
<br /><br /> <script><br /><br /> var nospace = "I dont need spaces".replace(" ","_");<br /><br /> alert(nospace); //I_dont need spaces - Only first occurence<br /><br /> var nospace = "I dont need spaces".replace(/ /g,"_");<br /><br /> alert(nospace); //I_dont_need_spaces<br /><br /> </script><br /><br />
7. ParseInt function
This is used to convert a string into an integer. The function does accept two arguments and the second argument specifies the radix. The radix here for decimal is10. If no radix argument is passed the parseInt function tries to guess the base and in this case because the string starts with 0, it is parsed as an octal number.
<br /><br /> <script><br /><br /> var str = "017";<br /><br /> var strInt = parseInt(str); //strInt = 15 ;)<br /><br /> var strInt = parseInt(str,10); //strInt = 17<br /><br /> </script><br /><br />
Please share your Javascript Gotcha’s using the form below:
(note use < and > to get past the comment filter for < and >)
Standard use of script tag
<script>
alert(1); //this works fine and alerts 1
<script>
However,
<script src=”exisingfile.js”>
alert(1); // this will not be called !!!
</script>
Surprisingly – If you have a script include then the contents are not executed.
Issue #1 happens in most languages.
Related to cross browser compatibility:
Using “var” is required or IE (6,7, 8?) throws errors
Also with IE (and this might be the correct behaviour), extraneous commas are syntax errors:
var myarray = [
1, 2, 3, 4, 5,
];
Very nice. I’d love to see you do a “round two”. Global versus local variables, scoping rules, that sort of thing.
@Josh : Yes and non programmers get caught by it every time. They expect a + b to be the same as b + a. Really it should be shouldn’t it?
some nice points in here, i definitely learned – thank you!
tho, to be picky…
the floating point rounding + unrepresentable representations are not JScript specific, presumably they are just the same-old IEEE floating point issues.
also, i am sad to live in a universe where people are more familiar with PHP’s behavior than Perl’s e.g. when it comes to how replace works. 🙂
regarding Floating point arithmetic, you should probably be using the toPrecision() or toFixed() method of Number instead of round, so your example would look like:
(.02/.1).toFixed(2)
“0.20”
but in reality, in situations like that, you should probably be starting with integers if possible (i.e. 2/10). This is one of those things that seems frustrating, but it’s pretty inconsistent among most programming languages because integers are a bit better behaved (although maths are still tricky, regardless).
For a good example, see docs.python.org/tutorial/floatingpoint.html
#3 is not strictly correct. If it were then doing this would be a problem:
myFunc(arg1,
arg2,
arg3);
JavaScript automatically inserts semi-colons after _some_ statements, the return statement being the classic example. And this is why it is good practice in JavaScript to put the opening brace on the same line as the preceding statement.
e.g. This returns a object as expected:
return {
key: value
}
This returns undefined because a semi-colon is inserted after the return statement:
return
{ key : value }
#6 well yes, because Javascript uses regular expressions for replacing…
@John Dehope: “They expect a + b to be the same as b + a. Really it should be shouldn’t it?”
It’s not even programming languages, it’s the IEEE standard. There’s a very basic reason for it when you think about it for 10 seconds.
Pingback: links for 2009-05-21 « My Weblog
Pingback: Pinderkent: Programming languages should not try to guess the programmer's intentions.
Alex, as established, JavaScript will insert semi-colons at the end of “statements” if they’re not there already. In your example, arg1, arg2 and arg3 are not statements – they’re “expressions”; JavaScript knows this and so doesn’t bother inserting any semi colons. Although you are right, #3 states that semi-colons are inserted at line-feeds; which is obviously incorrect.
As mentioned, the floating point stuff is not JavaScript specific. Here are two of the biggest fails I routinely see in other people’s code:
1. Not declaring local variables. When JavaScript encounters an undeclared variable, it will go searching up the scope chain.
function myFunction (x) {
for (i = 0 ; i < x ; i++) {
foo () ;
}
}
for (i = 0 ; i < 10 ; i++) {
myFunction (i) ;
}
In the above code, the “i” in myFunction() will refer to the global “i” producing some very odd results.
2. Using “for .. in” on arrays. “for .. in” is for iterating over OBJECT properties, not array values. In JavaScript, arrays are objects and “length” is a property of an array:
var a = [“hello”, “world”] ;
for (var i in a) {
alert (i + ‘: ‘ + a[i]) ;
}
The above code will result in three alerts, not the two that most people expect.
For #6, you can make JavaScript replace all by using the following syntax:
“I dont need spaces”.replace(” “,”_”, “ig”);
The 3rd paramter is the Regular expression modifier that tells it how to do the replacement.
i = case Insensitive
g = global (aka all matches)
One gotcha that’s more of a DOM issue than a Javascript one is to do with DOM0 and form.submit().
Basically any inputs you put into a form will be available in that form using the form.X where X is the inputs name. So if you have a submit button and you call it submit (the name not the type) this will override form.submit making the function unavailable to call.
Pingback: Does actionscript have javascript’s gotchas? | Coppery Keen Claws