是否有可能找出调用函数的位置?如果是,那么 如何从全局范围,另一个功能,或者从浏览器控制台中检测某个功能?
看看下面的例子:
<script>
function myFunc1() {
// some code
myFunc2(); // I was called from myFunc1()
}
function myFunc2() {
var callerName = new String;
callerName = arguments.callee.caller.name;
// some code
alert('I was called from ' + callerName + ' function');
}
myFunc2(); // I was called from global scope
</script>
我知道上面示例中的这一行callerName = arguments.callee.caller.name;
会给我调用函数的名称。但是我不知道如何检测函数是否被调用全局范围。例如,如果我更改myFunc2()
并添加if else
语句以检查arguments.callee.caller.name
是否返回undefined
值,则知道会发生这种情况,从全局范围调用函数时:
myFunc2() {
var callerName = new String;
callerName = arguments.callee.caller.name;
if(callerName == undefined) {
alert('I was called from global scope');
} else {
alert('I was called from ' + callerName + ' function');
}
}
但是,如果从全局范围调用myFunc2()
并且callerName = arguments.callee.caller.name;
将导致JavaScript抛出以下错误,则无效:
TypeError: 'null' is not an object (evaluating 'arguments.callee.caller.name')
所以我回到原点,问题仍然存在:
答案 0 :(得分:13)
在Chrome中,您可以使用:
console.trace();
只需在函数中添加该行,我通常将其作为第一行。如果您查看控制台,您将看到您的功能名称,在该行下方,您将看到它的调用位置。
答案 1 :(得分:7)
如果从全局范围调用该函数,则arguments.callee.caller.name
将是未定义的。否则,它将是调用函数的名称(也代表调用它的范围)。
所以你已经拥有的东西应该有效,除了strict mode,其中arguments.callee
不可用。
另外:浏览器中提供的开发人员工具可能是检查此类事情的更好方法:只需设置断点并查看堆栈跟踪面板。除非您的代码本身需要在运行时知道调用范围。
答案 2 :(得分:3)
根据您的浏览器,您可能会在try/catch
内访问未定义的变量而引发错误。然后检查一些浏览器在错误中提供的堆栈跟踪。
这将非常适合浏览器。
答案 3 :(得分:2)
function func1() {
// some code
func2(); // I was called from func1()
}
function func2() {
var callerName = new String;
callerName = arguments.callee.caller ? arguments.callee.caller.name : "global";
if(callerName == "global") {
alert('I was called from global scope');
} else {
alert('I was called from ' + callerName + ' function');
}
}
func1();
func2(); // I was called from global scope
&#13;
func2被调用它将显示其调用者名称,如果它在另一个函数范围内被调用,它将显示该函数的名称,如果它是从全局范围调用的,它将显示一条消息,显示它被调用来自全球范围。
答案 4 :(得分:1)
在JavaScript中,大多数东西都是对象,当您使用某些属性和方法声明callerName = new String
创建字符串对象时。例如,valueOf()
方法将返回字符串对象的原始值。但是,就像JavaScript告诉你'TypeError: 'null' is not an object
null不是对象但是,缺少对象。 null没有任何方法或属性。当从全局范围调用函数时,arguments.callee.caller
将调用者评估为 null。因此arguments.callee.caller.name
就像尝试访问 null的name
属性(null.name
),但是null 没有名为name
,的属性,因为它不是对象而根本不能拥有任何属性。这就是JavaScript抱怨的原因,因为您正在尝试 访问不存在的内容。 然而,您可以做的是首先检查是否{{1使用简单的caller
语句if else
,,如果不是,,则可以访问if(!arguments.callee.caller)
属性,这是一个虚假值 name
的{{1}},找出哪个函数调用了caller
,,但如果它是,那么你知道该函数是从全局范围调用的。
myFunc2()
答案 5 :(得分:1)
这是一个非常棘手的问题。正如在这个答案中讨论的那样,在某些浏览器中不推荐使用Arguments.callee。
根据您的方法,您可以使用Function.caller。 我写了一篇非常simple example
的文章function A() {
if (A.caller === null || A.caller.name == "") console.log("Function called from top window")
else console.log("Called from " + A.caller.name);
B();
}
function B() {
if (B.caller === null || B.caller.name == "") console.log("Function called from top window")
else console.log("Called from " + B.caller.name);
}
A();
可以找到另一个更通用的示例here
仍然'use strict'
使这两种方法失败,因此使用try / catch
块可以解决您的问题,或者您可以模拟&#34; dummy call stack&#34;为您的功能(取决于所有代码同步工作的事实)