arguments.callee

  • Revision slug: JavaScript/Reference/Functions_and_function_scope/arguments/callee
  • Revision title: callee
  • Revision id: 34139
  • Created:
  • Creator: stommepoes
  • Is current revision? No
  • Comment one or more formatting changes

Revision Content

Summary

Specifies the currently executing function.

Property of arguments
Implemented in JavaScript 1.2
ECMAScript Edition 3rd Edition

Description

callee is a property of the arguments object. It can be used to refer to the currently executing function inside the function body of that function. This is for example useful when you don't know the name of this function, which is for example the case with anonymous functions.

Note: You should avoid using arguments.callee() and just give every function (expression) a name.
Warning: The 5th edition of ECMAScript forbids use of arguments.callee() in strict mode.

Example: Using arguments.callee in an anonymous recursive function

A recursive function must be able to refer to itself. Typically, a function refers to itself by its name. However, an anonymous function does not have a name, and if there is no accessible variable referring to it, i.e. the function is not assigned to any variable, the function cannot refer to itself. (Anonymous functions can be created by a function expression or the Function constructor.) This is where arguments.callee comes in.

The following example defines a function, which, in turn, defines and returns a factorial function. This example isn't very practical, and there are nearly no cases where the same result can not be archived with named function expressions.

function create() {
   return function(n) {
      if (n <= 1)
         return 1;
      return n * arguments.callee(n - 1);
   };
}

var result = create()(5); // returns 120 (5 * 4 * 3 * 2 * 1)

A bug after the deprecation of arguments.callee?

Early versions of JavaScript did not allow named function expressions, and for this reason you could not make a recursive function expression.

For example, this syntax worked:

function factorial (n) {
 return !(n > 1) ? 1 : factorial(n - 1) * n;
}

[1,2,3,4,5].map(factorial);

but:

[1,2,3,4,5].map(function (n) {
  return !(n > 1) ? 1 : /* what goes here? */ (n - 1) * n;
});

did not. To get around this arguments.callee was added so you could do

[1,2,3,4,5].map(function (n) {
  return !(n > 1) ? 1 : arguments.callee(n - 1) * n;
});

However this was actually a really bad solution as this (in conjunction with other arguments, callee, and caller issues) make inlining and tail recursion impossible in the general case (you can achieve it in select cases through tracing etc, but even the best code is sub optimal due to checks that would not otherwise be necessary). The other major issue is that the recursive call will get a different this value, eg.

var global = this;
var sillyFunction = function (recursed) {
 if (!recursed) { return arguments.callee(true); }
 if (this !== global) { alert("This is: " + this); }
 else { alert("This is the global"); }
}
sillyFunction();

ECMAScript 3 resolved these issues by allowing named function expressions. For example:

[1,2,3,4,5].map(function factorial (n) {
  return !(n > 1) ? 1 : factorial(n-1)*n;
});

This has numerous benefits

  • the function can be called like any other from inside your code
  • it does not pollute the namespace
  • the value of this does not change
  • it's more performant (accessing the arguments object is expensive)

In addition to everything else, the question was about arguments.callee.caller, or more specifically Function.caller. At any point in time you can find the deepest caller of any function on the stack, and as I said above looking at the call stack has one single major effect: It makes a large number of optimizations impossible, or much much more difficult. For example, if you cannot guarantee that a function f will not call an unknown function it is not possible to inline f. Basically it means that any call site that may have been trivially inlinable accumulates a large number of guards, take:

function f (a, b, c, d, e) { return a ? b * c : d * e; }

If the JavaScript interpreter cannot guarantee that all the provided arguments are numbers at the point that the call is made, it needs to either insert checks for all the arguments before the inlined code, or it cannot inline the function. Now in this particular case a smart interpreter should be able to rearrange the checks to be more optimal and not check any values that would not be used. However in many cases that's just not possible and therefore it becomes impossible to inline.

However in a case like the following there are not alternatives to arguments.callee, so its deprecation could be a bug (see {{ Bug("725398") }}):

function createPerson (sIdentity) {
    var oPerson = new Function("alert(arguments.callee.identity);");
    oPerson.identity = sIdentity;
    return oPerson;
}

var john = createPerson("John Smith");

john();

{{ languages( { "es": "es/Referencia_de_JavaScript_1.5/Funciones/arguments/callee", "fr": "fr/R\u00e9f\u00e9rence_de_JavaScript_1.5_Core/Fonctions/arguments/callee", "ja": "ja/Core_JavaScript_1.5_Reference/Functions/arguments/callee", "pl": "pl/Dokumentacja_j\u0119zyka_JavaScript_1.5/Funkcje/arguments/callee" } ) }}

Revision Source

<h2 id="Summary">Summary</h2>
<p>Specifies the currently executing function.</p>
<table class="standard-table"> <tbody> <tr> <td class="header" colspan="2">Property of <a href="/en/JavaScript/Reference/Functions_and_function_scope/arguments" title="en/JavaScript/Reference/Functions_and_function_scope/arguments">arguments</a></td> </tr> <tr> <td>Implemented in</td> <td>JavaScript 1.2</td> </tr> <tr> <td>ECMAScript Edition</td> <td>3rd Edition</td> </tr> </tbody>
</table>
<h2 id="Description">Description</h2>
<p><code>callee</code> is a property of the <code>arguments</code> object. It can be used to refer to the currently executing function inside the function body of that function. This is for example useful when you don't know the name of this function, which is for example the case with anonymous functions.</p>
<div class="note"><strong>Note:</strong> You should avoid using <code>arguments.callee()</code> and just give every function (expression) a name.</div>
<div class="warning"><strong>Warning:</strong> The 5th edition of ECMAScript forbids use of <code>arguments.callee()</code> in strict mode.</div>
<h3 id="Example:_Using_arguments.callee_in_an_anonymous_recursive_function">Example: Using <code>arguments.callee</code> in an anonymous recursive function</h3>
<p>A recursive function must be able to refer to itself. Typically, a function refers to itself by its name. However, an anonymous function does not have a name, and if there is no accessible variable referring to it, i.e. the function is not assigned to any variable, the function cannot refer to itself. (Anonymous functions can be created by a <a href="/en/JavaScript/Reference/Operators/function" title="en/JavaScript/Reference/Operators/Special/function">function expression</a> or the <a href="/en/JavaScript/Reference/Global_Objects/Function" title="en/JavaScript/Reference/Global_Objects/Function"><code>Function</code> constructor</a>.) This is where <code>arguments.callee</code> comes in.</p>
<p>The following example defines a function, which, in turn, defines and returns a factorial function. This example isn't very practical, and there are nearly no cases where the same result can not be archived with <a href="/en/JavaScript/Reference/Operators/function" title="en/JavaScript/Reference/Operators/Special/function">named function expressions</a>.</p>
<pre class="brush: js">function create() {
   return function(n) {
      if (n &lt;= 1)
         return 1;
      return n * arguments.callee(n - 1);
   };
}

var result = create()(5); // returns 120 (5 * 4 * 3 * 2 * 1)
</pre>
<h2 id="A_bug_after_the_deprecation_of_arguments.callee?">A bug after the deprecation of <code>arguments.callee</code>?</h2>
<p>Early versions of JavaScript did not allow named function expressions, and for this reason you could not make a recursive function expression.</p>
<p>For example, this syntax worked:</p>
<pre class="brush: js"><code>function factorial (n) {
 return !(n &gt; 1) ? 1 : factorial(n - 1) * n;
}

[1,2,3,4,5].map(factorial);
</code></pre>
<p>but:</p>
<pre class="brush: js"><code>[1,2,3,4,5].map(function (n) {
  return !(n &gt; 1) ? 1 : /* what goes here? */ (n - 1) * n;
});
</code></pre>
<p>did not. To get around this <code>arguments.callee</code> was added so you could do</p>
<pre class="brush: js"><code>[1,2,3,4,5].map(function (n) {
</code><code>  return !(n &gt; 1) ? 1 : </code><code>arguments.callee(n - 1) * n;
});
</code></pre>
<p>However this was actually a really bad solution as this (in conjunction with other <code>arguments</code>, <code>callee</code>, and <code>caller</code> issues) make inlining and tail recursion impossible in the general case (you can achieve it in select cases through tracing etc, but even the best code is sub optimal due to checks that would not otherwise be necessary). The other major issue is that the recursive call will get a different <code>this</code> value, eg.</p>
<pre class="brush: js"><code>var global = this;
var sillyFunction = function (recursed) {
 if (!recursed) { return arguments.callee(true); }
 if (this !== global) { alert("This is: " + this); }
 else { alert("This is the global"); }
}
sillyFunction();
</code></pre>
<p>ECMAScript 3 resolved these issues by allowing named function expressions. For example:</p>
<pre class="brush: js"><code>[1,2,3,4,5].map(function factorial (n) {
</code><code>  return !(n &gt; 1) ? 1 : </code><code>factorial(n-1)*n;
});
</code></pre>
<p>This has numerous benefits</p>
<ul> <li>the function can be called like any other from inside your code</li> <li>it does not pollute the namespace</li> <li>the value of <code>this</code> does not change</li> <li>it's more performant (accessing the arguments object is expensive)</li>
</ul>
<p>In addition to everything else, the question was about <code>arguments.callee.caller</code>, or more specifically <code>Function.caller</code>. At any point in time you can find the deepest caller of any function on the stack, and as I said above looking at the call stack has one single major effect: It makes a large number of optimizations impossible, or much much more difficult. For example, if you cannot guarantee that a function <code>f</code> will not call an unknown function it is not possible to inline <code>f</code>. Basically it means that any call site that may have been trivially inlinable accumulates a large number of guards, take:</p>
<pre class="brush: js"><code>function f (a, b, c, d, e) { return a ? b * c : d * e; }
</code></pre>
<p>If the JavaScript interpreter cannot guarantee that all the provided arguments are numbers at the point that the call is made, it needs to either insert checks for all the arguments before the inlined code, or it cannot inline the function. Now in this particular case a smart interpreter should be able to rearrange the checks to be more optimal and not check any values that would not be used. However in many cases that's just not possible and therefore it becomes impossible to inline.</p>
<p>However in a case like the following there are not alternatives to <code>arguments.callee</code>, so its deprecation could be a bug (see {{ Bug("725398") }}):</p>
<pre class="brush: js">function createPerson (sIdentity) {
    var oPerson = new Function("alert(arguments.callee.identity);");
    oPerson.identity = sIdentity;
    return oPerson;
}

var john = createPerson("John Smith");

john();
</pre>
<p>{{ languages( { "es": "es/Referencia_de_JavaScript_1.5/Funciones/arguments/callee", "fr": "fr/R\u00e9f\u00e9rence_de_JavaScript_1.5_Core/Fonctions/arguments/callee", "ja": "ja/Core_JavaScript_1.5_Reference/Functions/arguments/callee", "pl": "pl/Dokumentacja_j\u0119zyka_JavaScript_1.5/Funkcje/arguments/callee" } ) }}</p>
Revert to this revision