JavaScript: Global By Default

September 1, 2008

Here's a very simple JavaScript function that prints the sum of its arguments:

``````function sum() {
s = 0;
for(i=0; i < arguments.length; i++) {
s += arguments[i];
}
return s;
}
document.write('sum = '+sum(1, 2, 3));
``````

Looks simple enough. Translated directly into non-idiomatic Ruby, that would be:

``````def sum(*args)
s = 0
i = 0
while i < args.length
s += args[i]
i += 1
end
s
end
``````

So let's say you now want your sum function to return the sum of the factorial of each number. No problem:

``````function sum() {
s = 0;
for(i=0; i < arguments.length; i++) {
s += factorial(arguments[i]);
}
return s;
}
function factorial(n) {
f = 1;
for(i=1; i <= n; i++) {
f *= i;
}
return f;
}
document.write('sum = '+sum(1, 2, 3));
``````

Oops. That prints `1`, but the answer we were looking for was `9`. Hmmm, let's translate it to ruby and see what we get:

``````def sum(*args)
s = 0
i = 0
while i < args.length
s += factorial(args[i])
i += 1
end
s
end
def factorial(n)
s = 1
i = 1
while i <= n
s = s * i
i += 1
end
s
end
puts sum(1, 2, 3)
``````

Ok, so Ruby gives us `9`. So what's up? The truth is that is not a direct translation. Here's the correct translation:

``````def sum(*args)
\$s = 0
\$i = 0
while \$i < args.length
\$s += factorial(args[\$i])
\$i += 1
end
\$s
end
def factorial(n)
\$s = 1
\$i = 1
while \$i <= n
\$s = \$s * \$i
\$i += 1
end
\$s
end
puts sum(1, 2, 3)
``````

This gives us the same result as the flawed JavaScript, which is `1`. As you can see, in both functions, the variables `s` and `i` are declared as global variables, which you can tell by the `\$` sigil. But in JavaScript, variables are global by default. That's right, the simple little innocuous-looking `i=0` in our JavaScript for loop defines a global variable. Here is the corrected JavaScript version:

``````function sum() {
var s = 0;
for(var i=0; i < arguments.length; i++) {
s += factorial(arguments[i]);
}
return s;
}
function factorial(n) {
var f = 1;
for(var i=1; i <= n; i++) {
f *= i;
}
return f;
}
document.write('sum = '+sum(1, 2, 3));
``````

The moral of the story is always prefix your variable declarations with `var`. If you are a web developer who writes JavaScript and this is news to you, stop what you are doing an read Douglas Crockford's JavaScript: The Good Parts.

Posted in Technology | Tags Javascript