Posts Tagged ‘callee’

arguments considered harmful

Tuesday, February 16th, 2010

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]
  // oops!
  console.log(obj); // {p: 2}
  console.log(ar);  // [1, 2]
function B(args) {
  // convenient innocent-looking local vars
  var o=args[0],
  // do something with the local variables
  o.p = 2;
  // 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.