3

I often need in a function f to retrieve a name of the method that points to f. For example. Let's say we have a getMethodName(obj, methodFunction) function that uses foreach on obj to find a property that is a link to methodFunction:

obj = { 
    foo : function() {
        var myName = getMethodName(obj, arguments.callee); // "foo"
    }
}

How do I do this in strict mode where arguments.callee is deprecated?

Bhargav Rao
  • 50,140
  • 28
  • 121
  • 140
tillda
  • 18,150
  • 16
  • 51
  • 70

2 Answers2

4

You can't do it. And you shouldn't do it in the first place, this is magic, your function should not depend on its caller etc. Change your design in order to make it work again.

arguments.callee and .caller have not only been removed because of being bad style, but also because they defeat optimization. Namely inlining, you can't inline something if you depend on the caller, nor on the function, since the code might have just put somewhere without the function around it.

Read: http://whereswalden.com/2010/09/08/new-es5-strict-mode-support-now-with-poison-pills/

Ivo Wetzel
  • 46,459
  • 16
  • 98
  • 112
1

It's worth pointing out, since I can't tell if you considered it, that if you simply supply a name to the function in the object literal, you can refer to it that way:

obj = { 
    foo : function METHODNAME() {
        var myName = getMethodName(obj, METHODNAME); // "foo"
    }
}

But beware: I think IE has a bug in release versions where this will define a function named METHODNAME in the enclosing scope (rather than making it accessible to that function only). By spec, however, this is perfectly kosher and works perfectly fine so long as you use a name not found anywhere in the function itself, or in code passed to eval if the function can call eval.

Jeff Walden
  • 7,008
  • 2
  • 38
  • 55
  • But suppose I want to do addEventListener("event", myfun.bind(this)); I now can't remove this listener without storing it somewhere, right? Because myfun.bind() returns a new function. That's super-lame. – Justin L. May 16 '12 at 16:11
  • That sounds right. Although I think "super-lame" is very much in the eye of the beholder -- it's just how the language and API work. And how else could it? Taking as a given that we don't want to expose GC behavior (so weak-reference-like behavior's out), you need some way to remove a listener you've previously added, that disambiguates among multiple listeners. Isn't removal by specifying the reference to remove the natural way? It's perhaps a bit awkward, but I'm not seeing a better way offhand. – Jeff Walden May 17 '12 at 08:12
  • Well, it worked great when I could use arguments.callee. The argument being made is that you lose nothing without it -- just name the function. I'm saying that in fact you do lose something, because you can't always name the function. So now I have to choose between disabling strict mode and incurring the annoyance (and potential leaks) of keeping track of all these event listeners manually. – Justin L. May 17 '12 at 14:09
  • You can't name the function if it's a bound function in any case. arguments.callee inside myfun is myfun, not the bound function that results from myfun.bind(this). So the elimination of arguments.callee in strict mode functions shouldn't mean anything for your bound-function case. Or am I missing something? – Jeff Walden May 18 '12 at 21:15
  • "arguments.callee inside myfun is myfun, not the bound function that results from myfun.bind(this)" -- I had no idea! How sad. – Justin L. May 19 '12 at 00:30
  • Yes...but also perhaps no. Consider that the hand-rolled bind implementations from which these semantics derived all also had arguments.callee as the original function, not the bound function. The cowpaths were paved exactly as originally traveled. And doing it this way means polyfills can be more correct and faithful to spec semantics. Still, it's perhaps a tradeoff. – Jeff Walden Jun 03 '12 at 02:39