如何找出在JavaScript中调用函数的位置?

时间:2013-06-30 16:37:11

标签: javascript function call

是否有可能找出调用函数的位置?如果是,那么 如何从全局范围另一个功能,或者从浏览器控制台中检测某个功能?

看看下面的例子:

<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')

所以我回到原点,问题仍然存在:

  • 如何检测是否从全局范围调用函数?
  • 如果是从全球范围调用,是来自浏览器控制台吗?

6 个答案:

答案 0 :(得分:13)

在Chrome中,您可以使用:

console.trace();

只需在函数中添加该行,我通常将其作为第一行。如果您查看控制台,您将看到您的功能名称,在该行下方,您将看到它的调用位置。

答案 1 :(得分:7)

如果从全局范围调用该函数,则arguments.callee.caller.name将是未定义的。否则,它将是调用函数的名称(也代表调用它的范围)。

所以你已经拥有的东西应该有效,除了strict mode,其中arguments.callee不可用。


另外:浏览器中提供的开发人员工具可能是检查此类事情的更好方法:只需设置断点并查看堆栈跟踪面板。除非您的代码本身需要在运行时知道调用范围。

答案 2 :(得分:3)

根据您的浏览器,您可能会在try/catch内访问未定义的变量而引发错误。然后检查一些浏览器在错误中提供的堆栈跟踪。

这将非常适合浏览器。

答案 3 :(得分:2)

&#13;
&#13;
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;
&#13;
&#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;为您的功能(取决于所有代码同步工作的事实)