如何找出在 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
How to find out where a function is called from in JavaScript?
提问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 else
statement to check if arguments.callee.caller.name
returns an undefined
value, 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.name
will 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.callee
is 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 String
you 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 object
null 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.caller
evaluates caller to null.Soarguments.callee.caller.name
is like trying to access null's name
property (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 caller
is a falsy valueby using a simple if else
statement if(!arguments.callee.caller)
, if it isn't,then you can access the name
property of the caller
and 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 object
null 不是一个对象,而是一个对象的缺失。null 没有任何方法或属性。当从全局范围arguments.callee.caller
调用函数时,调用者的计算结果为null。所以arguments.callee.caller.name
就像试图访问null 的name
属性 ( null.name
),但 null没有名为 的属性name
,因为它不是一个对象,不能有任何财产可言。这就是 JavaScript 抱怨的原因,因为您试图访问不存在的东西。但是,您可以做的是首先使用简单语句检查是否caller
为假值,如果不是,则可以访问 的属性并找出调用了哪个函数,但是如果是,则您知道该函数是从全局范围调用的。if else
if(!arguments.callee.caller)
name
caller
myFunc2()
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 / catch
block 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
块可以解决您的问题,或者您可以为您的函数模拟一个“虚拟调用堆栈”(取决于所有代码同步工作的事实)