在 chrome 开发工具中记录匿名函数

Logging anonymous function in the chrome dev tools

我有一些这样的代码:

obj.addEventListener('event', function(eventType) {
});

当我在 chrome web deveoper Profiler 中调试它时,我总是将其视为匿名函数,但我更愿意将其视为 eventType 的内容。

是否可以以某种方式重命名或包装它,最好以一种有效的方式,而不需要为每个 eventType 单独的函数?

或者是否可以像在时间轴中那样为探查器添加时间戳,以便我可以区分不同的事件类型?

谢谢!

您可以使用命名函数表达式为您的函数指定一个名称,该名称将显示在探查器中,而不是“(匿名函数)”:

obj.addEventListener('event', function myHandler(eventType) {
});

在上述情况下,处理程序将在分析器中显示为 "myHandler"。

我认为您需要澄清 "rename or wrap this somehow, preferable in an efficent way, without the need of a separate function for each eventType" 的意思。从您的示例来看,您似乎在为每种事件类型使用单独的函数。

您希望函数名称取决于其参数,"without the need of a separate function for each eventType"?
我觉得那真的是不可能的。
显然,一个函数保留了创建时分配给它的名称。

尝试以下操作:

var aaa = function()
{
    debugger;
};
var bbb = aaa;
delete aaa;
(function(){ var ccc = bbb; ccc(); })();

当我 运行 上面的代码时,我在调试器中看到 "aaa",我怀疑它在开发工具的其他部分会有所不同。

我虽然也许有人可以篡改 arguments.callee:

var aaa = function()
{
    console.log(arguments.callee.name);
    arguments.callee.name = 'bbb';
    console.log(arguments.callee.name);
    debugger;
};
(function()
{
    var ccc = aaa;
    console.log(ccc.name);
    ccc.name = 'ccc';
    console.log(ccc.name);
    ccc();
})();

但这四次在控制台上什么也没有记录,这与 arguments.callee.prototype.constructor.name 完全相同。
仅记录 arguments.callee.prototype 记录 aaa {},这表明该名称以某种方式在内部绑定。

所以如果不创建额外的功能,这几乎是不可能的。 您可以使用 one 名称作为函数名称,如 .

中所建议

除此之外,您别无选择,只能在运行时间创建一些函数。
这不会使它们在探查器中显示为不同的函数,但是,您可能应该有一个全局对象,您可以在该对象上分配创建的函数,以便您可以重用它们。

我建议采用以下设置:

使实际的处理函数成为全局函数,例如:

function actualEventHandler(eventType) { /* ... */ }

有一个全局对象来将您即时创建的函数存储到:

var handlerFunctions = {};

然后在您指定的事件处理函数中,检查当前事件类型的函数是否已经存在,否则创建一个名称基于该类型的函数:

obj.addEventListener('event', function(eventType)
{
    if(handlerFunctions[eventType] === undefined)
    {
        var ev = {};
        ev[eventType] = function(evType)
        {
            actualEventHandler(evType);
        }
        handlerFunctions[eventType] = ev[eventType];
    }
    handlerFunctions[eventType](eventType);
});

由于您无法使用字符串名称创建变量,因此我在这里使用临时对象 ev,因此函数名称将为 ev.<whatever>。如果您根本不需要任何前缀,则必须使用 eval().

编辑: 似乎在 Chrome 的较新版本中,使用临时对象的技巧不再有效,因为 Chrome 现在只显示 ev.(anonymous function)。你仍然可以用 eval 来做,只要 eventType 是一个有效的函数名:

obj.addEventListener('event', function(eventType)
{
    if(handlerFunctions[eventType] === undefined)
    {
        var fn = null;
        eval('fn = function ev_' + eventType + '(evType){ actualEventHandler(evType); };');
        handlerFunctions[eventType] = fn;
    }
    handlerFunctions[eventType](eventType);
});

然后您的函数将显示在以 ev_ 为前缀的堆栈跟踪中。

我不知道这在探查器中的反映有多好,所有这些函数仍然会有一个匿名函数(传递给 addEventListener 的函数 - 你可以给它起个名字,但我不确定这是否真的有帮助)并在内部调用 actualEventHandler,但它实际上应该显示所有事件类型的不同功能。