## 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*.