Javascript 获取可能通过角度范围的所有事件的列表$$听众人数?

Javascript 获取可能通过角度范围的所有事件的列表$$听众人数?,javascript,angularjs,angularjs-directive,angularjs-scope,dom-events,Javascript,Angularjs,Angularjs Directive,Angularjs Scope,Dom Events,在一个指令中,我试图获取给定范围可能捕获的所有事件名称的列表 观察scope对象时,我可以看到有一个$$listeners属性,它包含一个函数,还有一个$$listenersCount属性,它实际上似乎包含我定义的与给定范围相关的事件列表 我正在所显示的子作用域上侦听这些事件中的大多数,因此我假设这是一个列表,列出了“通过”给定作用域的所有事件,而不是特定作用域正在侦听的事件。不过,我不确定这些数字是什么意思 我找不到关于这些属性的任何文档,所以我假设它们是不应该用于此特定目的的内部对象 有没

在一个指令中,我试图获取给定范围可能捕获的所有事件名称的列表

观察scope对象时,我可以看到有一个
$$listeners
属性,它包含一个函数,还有一个
$$listenersCount
属性,它实际上似乎包含我定义的与给定范围相关的事件列表

我正在所显示的子作用域上侦听这些事件中的大多数,因此我假设这是一个列表,列出了“通过”给定作用域的所有事件,而不是特定作用域正在侦听的事件。不过,我不确定这些数字是什么意思

我找不到关于这些属性的任何文档,所以我假设它们是不应该用于此特定目的的内部对象


有没有其他方法来检索这样的列表,或者你认为它是安全的,尽管缺少文档?

让我们首先考虑使用$$侦听器。正如他在评论中引用的:

为了防止与代码发生意外的名称冲突,公共对象的名称前面加上$,私有对象的名称前面加上$$。请不要在代码中使用$或$$前缀

所以$$侦听器是angular的私有对象。它没有文档,可以在任何时候引入突破性的更改,而无需通知。而且这也不是你想要的。通过查看的代码,我们可以看到,正如您所猜测的,$$listenerCount将作用域冒泡到它的$parent,一直到root。这些数字表示有多少侦听器正在侦听一个事件。如果您正在开发一些内部工具来调试事件,那么使用$$监听器可能不受影响,但在生产站点中使用并不是最明智的做法


那么,实现这一目标的书面方法是什么呢?Angular在其提供程序上提供了一个。虽然关于这方面的文档很少,但它是一个非常强大的工具。它本质上允许截取任何角度的角度,并充当中间人(在维基百科上看到更多信息)。使用这些工具,我们可以创建一个配置,在调用时捕获$1的每个实例:

.config(function ($provide) {
    function wrap(oldFn, wrapFn) {
        return function () {
            return wrapFn.bind(this, oldFn)
                         .apply(this, arguments);
        }
    }

    $provide.decorator('$rootScope', function ($delegate) {
        var proto = Object.getPrototypeOf($delegate);

        proto.$on = wrap(proto.$on, function ($on, name, listener) {
            var deregister = $on.call(this, name, listener);
            console.log(this, name, listener, deregister);
            return deregister;
        });

        return $delegate;
    });
});
每次调用$on时,我都会在这里登录。$scope是
this
变量,
name
listener
是传递给$on的参数,
delegister
是返回值。注意,his需要ES5,并且每次调用$on时都会增加开销

从这里,获取潜在的事件侦听器很容易。代替console.log,您可以将它们放在映射中,或者挂接到特定的映射中。你也可以把听者或听者包装起来,在每次接到电话时做额外的工作。这是一个例子


这比使用$$侦听器要好,因为$$侦听器可以在任何时间以任何方式更改$另一方面,是一个已发布的API。它将更加稳定,如果angular的changelog中没有“中断更改”通知,它将不会更改,并且是更安全的选择,即使它使用了更多异常工具。

,但我想我们可以在这里找到一个非常好的答案;)。仅供参考,以
$$
开头的属性是严格私有的,不应使用(例如,BC是不保证的)。@Blackhole哈,是的,我一直在想这些属性的外观是什么,看起来很奇怪,果然是双美元“为防止与代码发生意外的名称冲突,公共对象的名称前面加上
$
,私有对象的名称前面加上
$$
。请不要在代码中使用
$
$
前缀。”