如何知道函数作用域上的javascript事件源? 问题:

如何知道函数作用域上的javascript事件源? 问题:,javascript,events,javascript-events,Javascript,Events,Javascript Events,在没有原始事件参数的情况下,是否可以知道函数是由用户事件还是异步事件(如回调)触发的 背景 我试图在一个更深层次的函数调用中确定事件源,它不知道谁是原始事件触发器 我必须知道,为了调用弹出或重定向登录系统。但是这个函数是从很多地方调用的,所以我不能在所有调用者中传递事件参数 重要信息:我无法将参数传递给最终函数b(“计时器”) e、 g: 这是 任何其他方法?可以在最里面的函数中抛出异常,捕获它,并使用异常确定调用堆栈 如何获取调用堆栈的详细信息是特定于供应商的(FF中的e.stack,Oper

在没有原始事件参数的情况下,是否可以知道函数是由用户事件还是异步事件(如回调)触发的

背景 我试图在一个更深层次的函数调用中确定事件源,它不知道谁是原始事件触发器

我必须知道,为了调用弹出或重定向登录系统。但是这个函数是从很多地方调用的,所以我不能在所有调用者中传递事件参数

重要信息:我无法将参数传递给最终函数<不允许使用代码>b(“计时器”)

e、 g:

这是


任何其他方法?

可以在最里面的函数中抛出异常,捕获它,并使用异常确定调用堆栈

如何获取调用堆栈的详细信息是特定于供应商的(FF中的
e.stack
,Opera中的
e.message
,IE和Safari中的粗略函数体解析),但在上存在一个相当健壮的实现

至少,这是我从该页面上发布的简短片段中可以看出的。请注意,这已经演变成了一个,因此可能比该页面上的50行代码片段更可靠,功能更丰富

在您的示例中,您将使用:

function b(){
    final();
}
function final(){
   var trace = printStackTrace();
   //output trace
}


//This would be attached as the click handler for the anchor
function anchorHandler(){
   b();
}
setTimeout(function timerCallback(){
    b();
}, 1000);

根据跟踪中是
timerCallback
还是
anchorHandler
,您知道触发函数调用的事件。

您可以使用arguments.callee.caller访问函数对象并附加expando。。。不确定这是否适用于您的情况。请注意,这在严格模式下无法工作,因为arguments.callee.caller已被弃用

<a onclick="b()" >call</a>

<script>

   function a(){
      b.calledByA = true;
      b();
   }

   function b(){
      final();
   }

   function final(){
      var caller = arguments.callee.caller;
      console.log(caller.calledByA);
      caller.calledByA = null;
   }

   setTimeout(a, 1000);

</script>
呼叫
函数a(){
b、 calledByA=true;
b();
}
函数b(){
最后的();
}
函数final(){
var caller=arguments.callee.caller;
console.log(caller.calledByA);
caller.calledByA=null;
}
设置超时(a,1000);

假设您至少可以在第一个函数
中通过“timer”:

呼叫
函数a(){
b();
}
函数b(){
最后的();
}
函数final(){
var callerFunction=arguments.callee.caller;
var evtArg=callerFunction.arguments[0];
while(callerFunction.caller!==null){
callerFunction=callerFunction.caller;
if(调用者函数参数[0]){
evtArg=callerFunction.arguments[0];
}
}
控制台日志(evtArg);
}
setTimeout(函数(){a(“计时器”)},100);
这将获得函数调用链中最后一个可能的第一个参数。因此,如果您使用“正常”事件,它将为您提供事件对象。如果您使用超时,它将为您提供传递给第一个函数的任何内容


请注意,此解决方案还使用
arguments.callee.caller
,这应该很慢,并且不受任何地方的支持。正如robC已经提到的,在严格模式下是不允许的。

为什么不能将参数传递给
b
?您定义
a
的目的是什么?因此
b(“计时器”)
是不可能的,但是否可以至少传递一些信息给事件调用的第一个函数(to
a
)?@Asad:对不起,我更新了我的示例,现在调用了a()。@user1737909:我无法将参数传递给b,因为在我的实际代码中,b是来自各个地方的文档的调用,其中许多是我无法管理的。“并使用异常来确定调用堆栈”-这让我有点发抖…天哪,听起来像地狱一样简略。非常切肉!,然而,我为我的问题找到了一个更简单的解决方案。坦克斯!arguments.callee.caller也是我的第一个想法,但它仍然不会告诉他调用了什么类型的事件
a
(超时)。如果编程调用总是在b上设置expandos,则可以通过演绎来完成。这就是我要找的。:)
function b(){
    final();
}
function final(){
   var trace = printStackTrace();
   //output trace
}


//This would be attached as the click handler for the anchor
function anchorHandler(){
   b();
}
setTimeout(function timerCallback(){
    b();
}, 1000);
<a onclick="b()" >call</a>

<script>

   function a(){
      b.calledByA = true;
      b();
   }

   function b(){
      final();
   }

   function final(){
      var caller = arguments.callee.caller;
      console.log(caller.calledByA);
      caller.calledByA = null;
   }

   setTimeout(a, 1000);

</script>
<a onclick="a()" >call</a>

<script>

function a(){
    b();
}

function b(){
    final();
}

function final(){
    var callerFunction = arguments.callee.caller;
    var evtArg = callerFunction.arguments[0];
    while (callerFunction.caller !== null) {
        callerFunction = callerFunction.caller;
        if (callerFunction.arguments[0]) {
            evtArg = callerFunction.arguments[0];
        }
    }
    console.log(evtArg);
}

setTimeout(function(){a("timer")}, 100);

</script>