43

For doing things like

setTimeout(function () {
    ...
    setTimeout(arguments.callee, 100);
}, 100);

I need something like arguments.callee. I found information at javascript.info that arguments.callee is deprecated:

This property is deprecated by ECMA-262 in favor of named function expressions and for better performance.

But what should be then used instead? Something like this?

setTimeout(function myhandler() {
    ...
    setTimeout(myhandler, 100);
}, 100);
// has a big advantage that myhandler cannot be seen here!!! 
// so it doesn't spoil namespace

BTW, is arguments.callee cross-browser compatible?

Joe
  • 41,484
  • 20
  • 104
  • 125
Tomas
  • 57,621
  • 49
  • 238
  • 373
  • 2
    For what it's worth: [Named function expressions demystified](http://kangax.github.com/nfe/). – sdleihssirhc Dec 02 '11 at 19:46
  • Yes, you should name your function and use its name in setTimeout. – kubetz Dec 02 '11 at 19:46
  • 2
    possible duplicate of [Why was the arguments.callee.caller property deprecated in JavaScript?](http://stackoverflow.com/questions/103598/why-was-the-arguments-callee-caller-property-deprecated-in-javascript) – cHao Dec 02 '11 at 19:56
  • 1
    @cHao, nope, that's not a duplicate: arguments.callee.caller deprecation **doesn't imply deprecation of the whole arguments.callee**. Moreover, this question doesn't ask **"what should be used instead!"** – Tomas Dec 02 '11 at 20:08
  • @Tomas: Check the answers. Everything you've asked is mentioned within them. – cHao Dec 02 '11 at 21:14

3 Answers3

11

Yes, that's what, theoretically, should be used. You're right. However, it doesn't work in some versions of Internet Explorer, as always. So be careful. You may need to fall back on arguments.callee, or, rather, a simple:

function callback() {
    // ...
    setTimeout(callback, 100);
}

setTimeout(callback, 100);

Which does work on IE.

Ry-
  • 218,210
  • 55
  • 464
  • 476
  • 1
    Wait - you want to say that `setTimeout(function myhandler() { setTimeout(myhandler ...` will not work in some versions of IE? Is this a non-standard thing? I thought it is a pretty standard thing to do. – Tomas Dec 03 '11 at 07:35
  • 3
    @TomasT.: It *is* standard - but since when has IE ever been completely standard? :) (Well, maybe IE10.) I remember being tripped up by it some time. A quick test reveals that it's not an issue in IE7 at least. Probably IE6. I don't have it with me to test. – Ry- Dec 03 '11 at 15:52
  • According to Microsoft, it works in IE6: https://learn.microsoft.com/en-us/scripting/javascript/reference/callee-property-arguments-javascript – Jack G Apr 04 '17 at 21:48
  • @lolzerywowzery: That’s `arguments.callee`, not named function expressions. There are three periods of named function expressions in IE, IIRC: not working at all, leaking into the surrounding scope, and working according to spec. – Ry- Apr 04 '17 at 22:12
5

But what should be then used instead? Something like this?

Yes, you answered your own question. For more information, see here:

Why was the arguments.callee.caller property deprecated in JavaScript?

It has a pretty good discussion about why this change was made.

Community
  • 1
  • 1
Jonathan Rich
  • 1,740
  • 10
  • 11
1

minitech answer is quite good, but it is missing one more scenario. Your declare function called callback, which means two things, first the function is object in memory, and the second, the function name is only for referencing to the object. If you, for any reason break the reference between these two, the proposed code will not work too.

Proof:

function callback() {
    // ...
    setTimeout(callback, 100);
}

setTimeout(callback, 100);

var callback2 = callback; //another reference to the same object
callback = null; //break the first reference
callback2(); //callback in setTimeout now is null.

From developer Mozilla page in the description is:

Warning: The 5th edition of ECMAScript (ES5) forbids use of arguments.callee() in strict mode. Avoid using arguments.callee() by either giving function expressions a name or use a function declaration where a function must call itself.

obviously this is the first example of workaround "by either giving function expressions a name", but lets see how we can deal with "or use a function declaration where a function must call itself" and what will that bring:

function callback(){
   //...
   setTimeout(innercall(), 100);
   function innercall(){
      //innercall is safe to use in callback context
      innercall.caller(); //this will call callback();
   }
}

Then we are safe to do whatever we want with the callback reference:

var callback2 = callback;
callback = null;
callback2(); //will work perfectly.
lowselfesteemsucks
  • 825
  • 1
  • 13
  • 21
  • `caller` isn’t good practice, and the sample code here doesn’t actually seem to set a timeout. Just don’t overwrite your declared function. – Ry- Dec 05 '16 at 11:08