如何知道函数作用域上的JavaScript事件源
How to know the JavaScript event source on function scope?
问题
在没有原始事件参数的情况下,是否可以知道函数是由用户事件还是异步事件(如回调(触发的?
背景
我试图在一个更深层次的函数调用中确定事件源,该函数不知道谁是最初的事件触发器。
我必须知道,为了调用弹出或重定向登录系统。但是这个函数是从很多地方调用的,所以我不能在所有调用方中传递事件参数。
重要:我无法将参数传递给最终函数。不允许使用b('timer')
。
例如:
<a onclick="b()" >call</a>
<script>
function a(){
b();
}
function b(){
final();
}
function final(){
//Is there something like this caller.event.source ?
console.log(this.caller.event.source)
}
setTimeout(a,1000);
在该示例中,我试图获取source == 'timer'
或'onclick'
,或任何其他信息,以确定哪个是事件起源。
更新
基于basilikun方法,我实现了这个解决方案:
function final(){
var callerFunction = arguments.callee.caller,
evtArg = callerFunction.arguments[0];
while(callerFunction.caller){
callerFunction = callerFunction.caller;
if (callerFunction.arguments[0]) {
evtArg = callerFunction.arguments[0];
}
}
console.log(evtArg&&evtArg.type?'event fired by user':'event async');
}
这是finddle
还有其他方法吗?
可以在最内部的函数中抛出异常,捕获它,并使用该异常来确定调用堆栈。
如何获得调用堆栈的细节是特定于供应商的(FF中的e.stack
,Opera中的e.message
,IE和Safari中的粗略函数体解析(,但eriwen.com上存在一个相当稳健的实现。
至少,这是我可以从该页面上发布的简短片段中了解到的。请注意,这已经发展成为Github上的一个完整的项目,因此可能比该页面上的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
,您可以知道是什么事件触发了函数调用。
假设您至少可以在第一个函数a
:中传递"计时器">
Fiddle
<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>
这将获得函数调用链中最后一个可能的第一个参数。因此,如果您使用"正常"事件,它将为您提供事件对象。如果你使用超时,它会给你传递给第一个函数的任何信息。
请注意,此解决方案还使用arguments.callee.caller
,它被认为是缓慢的,并且不是所有地方都支持它。正如robC已经提到的,在严格模式下是不允许的。
您可以使用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>
- JavaScript:在源404上重试
- 如何将javascript事件从web浏览器wpf控件发送到wpf的c#代码
- 关闭第二个事件源上的第一个事件源's onopen方法
- 在同一个javascript事件处理程序中调用不同的函数
- Javascript事件;在新选项卡中打开”;
- 存在每个时间元素的javascript事件
- Javascript事件.锚的目标问题
- 带有参数的Javascript事件处理程序
- 如何从另一个处理程序内部取消JavaScript事件处理程序函数的执行
- firefox中的Javascript事件范围问题
- Firefox中的JavaScript事件参数
- 在动态加载的PHP表单上放置JavaScript事件
- 如何在Javascript事件上从JSNI设置GWTClass字段
- Javascript事件发射器一次处理多个事件
- 在下拉式javascript事件监听器中选择时触发事件
- 在javascript中导入xlsx文件时,如何手动强制javascript事件
- 显示触发的JavaScript事件
- 正在取消IE11中的JavaScript事件
- 页面卸载期间的JavaScript事件循环
- 如何知道函数作用域上的JavaScript事件源