arguments
considered harmful
Inside every JavaScript function an arguments
object is available containing all the parameters passed to the function.
function aha(a, b) { console.log(arguments[0] === a); // true console.log(arguments[1] === b); // true } aha(1, 2);
However, it's not a good idea to use arguments
for the reasons of :
- performance
- security
The arguments
object is not automatically created every time the function is called, the JavaScript engine will only create it on-demand, if it's used. And that creation is not free in terms of performance. The difference between using arguments vs. not using it could be anywhere between 1.5 times to 4 times slower, depending on the browser (more info and bench)
As for the security, there is the POLA (Principle of Least Authority) which is violated when one function A passes arguments
to another B. Then a number of bad things can happen including:
- B calls A through arguments.callee - something A never intended when calling B in the first place
- B overwrites some
arguments
and causes A to misbehave
While in these scenarios B looks a little malicious, it can actually cause trouble unvoluntarilly. Consider this example that illustrates the second case (B changing values behind A's unsuspecting back)
function A(obj, ar) { console.log(obj); // {p: 1} console.log(ar); // [1, 2, 3] B(arguments); // oops! console.log(obj); // {p: 2} console.log(ar); // [1, 2] } function B(args) { // convenient innocent-looking local vars var o=args[0], a=args[1]; // do something with the local variables o.p = 2; a.pop(); // now the original arguments is // messed up because objects/arrays // are passed by reference } A({p: 1}, [1, 2, 3]);
ECMAScript 5
In ECMAScript's "strict mode", using arguments.callee
will throw a syntax error.
Recursive anonymous function
Probably the biggest argument for keeping arguments
and arguments.callee
is so that recursive anonymous functions can be created, because by using the callee
property a function can call itself without knowing its own name. Now, this is not such a common scenario, but even if so, you can wrap a named function inside of an anonymous function and voila! - call that named function recursively without leaking a variable to the global scope.