在严格模式的JavaScript中检索"self"函数

3

我经常需要在一个函数f中获取指向f的方法名称。例如,假设我们有一个getMethodName(obj,methodFunction)函数,它在obj上使用foreach来查找一个属性,该属性是指向methodFunction的链接:

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

严格模式下,如何处理arguments.callee被废弃的情况?

2个回答

4
您不能做它,而且您本来就不应该这么做,这是魔法,您的函数不应该依赖于其调用者等。改变您的设计以使其再次工作。 arguments.callee.caller 被移除不仅因为它们是不好的风格,而且因为它们破坏了优化。具体来说,在线性内嵌中,如果您依赖于调用者或函数,则无法内嵌某些内容,因为代码可能会被放在没有该函数的周围。
请阅读:http://whereswalden.com/2010/09/08/new-es5-strict-mode-support-now-with-poison-pills/

为什么这篇文章开头要用“tl;dr”?我知道它的一般含义,但不知道在这个上下文中是什么意思。 - Šime Vidas
嗯,我猜作者只是在开玩笑,因为他的文章基本上就是一个巨大的文字墙。 - Ivo Wetzel
啊哈,那只是一个玩笑。可能就是这样。 - Šime Vidas
是的,这只是一个玩笑 - 更确切地说,是对那些不愿意阅读超过一页的文章的人的温和讽刺。 :-) (还有:感谢引荐日志!) - Jeff Walden

1
值得指出的是,由于我无法确定你是否考虑过这一点,如果你在对象字面量中简单地提供一个函数名,你可以以这种方式引用它:
obj = { 
    foo : function METHODNAME() {
        var myName = getMethodName(obj, METHODNAME); // "foo"
    }
}

但要注意:我认为IE在发布版本中存在一个错误,即这将在封闭作用域中定义一个名为METHODNAME的函数(而不是仅使其对该函数可访问)。 但是,按照规范,只要您使用在函数本身或传递给eval的代码中找不到的名称,或者如果函数可以调用eval,则这是完全合法的,并且可以正常工作。


但是假设我想要执行addEventListener("event", myfun.bind(this));现在我不能删除这个监听器而不将其存储在某个地方,对吧?因为myfun.bind()返回一个新函数。这太烦人了。 - Justin L.
听起来没错。虽然我认为“超级糟糕”很大程度上取决于观察者的眼光——这只是语言和API的工作方式。否则还有什么其他方法呢?假设我们不想暴露GC行为(因此弱引用类似的行为被排除在外),您需要一种方法来删除先前添加的侦听器,以消除多个侦听器之间的歧义。通过指定要删除的引用进行删除不是自然的方式吗?这可能有点笨拙,但我目前没有看到更好的方法。 - Jeff Walden
当我可以使用arguments.callee的时候,这个函数运行得很好。争论的重点是:如果不使用它,你不会失去任何东西——只需要给函数命名即可。但我认为实际上你确实会失去一些东西,因为你并不能总是给函数命名。所以现在,我必须在禁用严格模式和手动跟踪所有这些事件侦听器之间做出选择,以避免麻烦(和潜在泄漏)的情况发生。 - Justin L.
无论如何,如果它是一个绑定函数,你不能给函数命名。在myfun内部的arguments.callee是myfun,而不是由myfun.bind(this)产生的绑定函数。因此,在严格模式函数中消除arguments.callee对于绑定函数的情况不应该有任何影响。或者我错过了什么? - Jeff Walden
"myfun内的arguments.callee是myfun本身,而不是通过myfun.bind(this)绑定后的函数。" -- 我之前完全不知道!太遗憾了。 - Justin L.
是的...但也可能不是。请考虑手动编写的绑定实现,这些语义派生自原始函数,而不是绑定函数。这些套路都是按照最初的方式铺设的。以这种方式进行操作意味着填充可以更正确地遵循规范语义。然而,这可能是一种权衡。 - Jeff Walden

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接