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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/17392534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 08:10:03  来源:igfitidea点击:

How to find out where a function is called from in JavaScript?

javascriptfunctioncall

提问by ilgaar

Is it possible to find out where a function is called from?If yes, then how to detect, if a function is called from a global scope, from another function, or perhaps from a browser console?

是否有可能找出一个函数是从哪里调用的?如果是,那么如何检测一个函数是从全局范围另一个函数还是从浏览器控制台调用的

Take a look at the following example:

看看下面的例子:

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

I know that this line callerName = arguments.callee.caller.name;in the example above, would give me caller function's name.But I don't know how to detect if a function was called from a global scope.For instance if I change myFunc2()and add an if elsestatement to check if arguments.callee.caller.namereturns an undefinedvalue, knowing that this will happen, when a function is called from a global scope:

我知道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');
    }
}

However, this will not work if myFunc2()is called from a global scope and callerName = arguments.callee.caller.name;will cause JavaScript to throw the following error:

但是,如果myFunc2()从全局范围调用,这将不起作用,并且callerName = arguments.callee.caller.name;会导致 JavaScript 抛出以下错误:

TypeError: 'null' is not an object (evaluating 'arguments.callee.caller.name')

So I am back to square one, and the question still remains:

所以我回到第一个,问题仍然存在:

  • How to detect if a function is called from a global scope?
  • If it's called from a global scope, is it from a browser console?
  • 如何检测是否从全局范围调用函数
  • 如果它是从全局范围调用的,它是从浏览器控制台调用的吗?

回答by Gene Parcellano

In Chrome, you can use:

在 Chrome 中,您可以使用:

console.trace();

Just add that line in your function, I usually place it as the first line. If you view the console you'll see the name of your function, and below that line you'll see where it's being called from.

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

回答by bfavaretto

If the function is called from the global scope, arguments.callee.caller.namewill be undefined. Otherwise, it will be the name of the caller function (which also represents the scope it was called from).

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

So what you already have should work, except in strict mode, where arguments.calleeis not available.

所以你已经拥有的应该可以工作,除非在严格模式arguments.callee不可用。



Additionaly: the developer tools available from your browser are probably a better way to inspect this kind of thing: just set a breakpoint and look at the stack trace panel. Unless of course your code itself needs to know the calling scope at runtime.

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

回答by HBP

Depending on your browser, you could provoke and error, by accessing an undefined variable for example, inside a try/catch. Then examine the stack trace some browsers provide in the error.

根据您的浏览器,您可能会通过访问未定义的变量(例如,在try/catch. 然后检查一些浏览器在错误中提供的堆栈跟踪。

This will be very browser specific.

这将是非常特定于浏览器的。

回答by vickisys

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

func2 is called it will display its caller name, if it was called within another function scope, it will display that function's name and if it was called from global scope it will display a message that shows it was called from the global scope.

func2 被调用它将显示其调用者名称,如果它在另一个函数范围内被调用,它将显示该函数的名称,如果它是从全局范围调用的,它将显示一条消息,表明它是从全局范围调用的。

回答by ilgaar

In JavaScript most things are objects, when you declare callerName = new Stringyou create a string objectwith some properties and methods. For instance, the valueOf()method will return the primitive value of a string object.However, just like JavaScript tells you 'TypeError: 'null' is not an objectnull is not an objectbut rather, it's the absence of an object.null doesn't have any methods or properties.When a function is called from a global scope, arguments.callee.callerevaluates caller to null.Soarguments.callee.caller.nameis like trying to access null's nameproperty (null.name), but null doesn't have a property called name,since it's not an object and can nothave any property at all. This is why JavaScript complains, because you are trying to access something that doesn't exist.What you can do however, is to first check if calleris a falsy valueby using a simple if elsestatement if(!arguments.callee.caller), if it isn't,then you can access the nameproperty of the callerand find out what function has called myFunc2(), but if it is, then you know the function was called from a global scope.

在 JavaScript 中,大多数东西都是对象,当您声明时,您callerName = new String会创建一个具有一些属性和方法的字符串对象。例如,该valueOf()方法将返回字符串对象原始值。然而,就像 JavaScript 告诉你'TypeError: 'null' is not an objectnull 不是一个对象,而是一个对象的缺失。null 没有任何方法或属性。当从全局范围arguments.callee.caller调用函数时,调用者的计算结果为null。所以arguments.callee.caller.name就像试图访问null 的name属性 ( null.name),但 null没有名为 的属性name因为它不是一个对象,不能有任何财产可言。这就是 JavaScript 抱怨的原因,因为您试图访问不存在的东西。但是,您可以做的是首先使用简单语句检查是否caller为假值如果不是,则可以访问 的属性并找出调用了哪个函数,但是如果是,则您知道该函数是从全局范围调用的。if elseif(!arguments.callee.caller)namecallermyFunc2()

function myFunc2() {
    if(!arguments.callee.caller) {
        callerName = "global";
        alert('I was called from global scope');
    } else {
        callerName = arguments.callee.caller.name;
        alert('I was called from ' + callerName + ' function');
    }
}

回答by vorillaz

That's quite a tricky question. As discussed on this answer Arguments.callee is deprecated in some browsers.

这是一个相当棘手的问题。正如在这个答案中所讨论的,Arguments.callee 在某些浏览器中已被弃用。

Depending on your approach you can use Function.caller. I have written a quite simple example

根据您的方法,您可以使用 Function.caller。我写了一个非常简单的例子

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();

Another more generic example can be found here

另一个更通用的例子可以在这里找到

Still 'use strict'makes both these approaches fail, so using a try / catchblock can solve your problem or you may simulate a "dummy call stack" for your functions ( depending on the fact that all your code works synchronously )

仍然'use strict'使这两种方法都失败,因此使用try / catch块可以解决您的问题,或者您可以为您的函数模拟一个“虚拟调用堆栈”(取决于所有代码同步工作的事实)