Answers:
在ES5及更高版本中,无法访问该信息。
在旧版JS中,您可以使用来获得它arguments.callee
。
但是,您可能必须解析名称,因为它可能包括一些额外的垃圾。不过,在某些实现中,您可以使用arguments.callee.name
。
解析:
function DisplayMyName()
{
var myName = arguments.callee.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
alert(myName);
}
arguments.callee
是在严格模式下是不允许的。
对于非匿名函数
function foo()
{
alert(arguments.callee.name)
}
但是如果是错误处理程序,结果将是错误处理程序函数的名称,不是吗?
您所需要的一切都很简单。创建函数:
function getFuncName() {
return getFuncName.caller.name
}
之后,只要需要,您只需使用:
function foo() {
console.log(getFuncName())
}
foo()
// Logs: "foo"
function getFuncName() { return getFuncName.name }
getFuncName
而不是其调用方的名称。
应该这样做:
var fn = arguments.callee.toString().match(/function\s+([^\s\(]+)/);
alert(fn[1]);
对于呼叫者,只需使用caller.toString()
。
[
这必须归类为“世界上最丑陋的骇客”类别,但是您可以在这里找到。
首先,对我来说,打印当前函数的名称(与其他答案一样)似乎用途有限,因为您已经知道该函数是什么!
但是,找出调用函数的名称对于跟踪函数可能非常有用。这是一个正则表达式,但是使用indexOf大约快三倍:
function getFunctionName() {
var re = /function (.*?)\(/
var s = getFunctionName.caller.toString();
var m = re.exec( s )
return m[1];
}
function me() {
console.log( getFunctionName() );
}
me();
这是一种可行的方法:
export function getFunctionCallerName (){
// gets the text between whitespace for second part of stacktrace
return (new Error()).stack.match(/at (\S+)/g)[1].slice(3);
}
然后在您的测试中:
import { expect } from 'chai';
import { getFunctionCallerName } from '../../../lib/util/functions';
describe('Testing caller name', () => {
it('should return the name of the function', () => {
function getThisName(){
return getFunctionCallerName();
}
const functionName = getThisName();
expect(functionName).to.equal('getThisName');
});
it('should work with an anonymous function', () => {
const anonymousFn = function (){
return getFunctionCallerName();
};
const functionName = anonymousFn();
expect(functionName).to.equal('anonymousFn');
});
it('should work with an anonymous function', () => {
const fnName = (function (){
return getFunctionCallerName();
})();
expect(/\/util\/functions\.js/.test(fnName)).to.eql(true);
});
});
请注意,只有在/ util / functions中,第三项测试才有效
getMyName
以下代码段中的函数返回调用函数的名称。这是一个hack,它依赖于非标准功能:Error.prototype.stack
。请注意,返回的字符串格式Error.prototype.stack
在不同的引擎中以不同的方式实现,因此这可能不适用于所有地方:
function getMyName() {
var e = new Error('dummy');
var stack = e.stack
.split('\n')[2]
// " at functionName ( ..." => "functionName"
.replace(/^\s+at\s+(.+?)\s.+/g, '$1' );
return stack
}
function foo(){
return getMyName()
}
function bar() {
return foo()
}
console.log(bar())
关于其他的解决方案:arguments.callee
是不是在严格模式下允许的和Function.prototype.caller
是非标准和严格模式不允许的。
另一个用例可能是在运行时绑定的事件分派器:
MyClass = function () {
this.events = {};
// Fire up an event (most probably from inside an instance method)
this.OnFirstRun();
// Fire up other event (most probably from inside an instance method)
this.OnLastRun();
}
MyClass.prototype.dispatchEvents = function () {
var EventStack=this.events[GetFunctionName()], i=EventStack.length-1;
do EventStack[i]();
while (i--);
}
MyClass.prototype.setEvent = function (event, callback) {
this.events[event] = [];
this.events[event].push(callback);
this["On"+event] = this.dispatchEvents;
}
MyObject = new MyClass();
MyObject.setEvent ("FirstRun", somecallback);
MyObject.setEvent ("FirstRun", someothercallback);
MyObject.setEvent ("LastRun", yetanothercallback);
这样做的优点是可以轻松地重用调度程序,并且不必将调度队列作为参数来接收,而是使用调用名称隐式地分配了调度程序...
最后,这里介绍的一般情况是“使用函数名称作为参数,因此您不必显式传递它”,这在许多情况下可能很有用,例如jquery animate()可选回调,或在超时/间隔回调中(即,您仅传递函数名称)。
自从提出这个问题以来,当前功能的名称及其获取方式似乎在过去10年中发生了变化。
现在,不是成为一个专业的Web开发人员,不知道所有存在的所有浏览器的所有历史,这是它在2019年chrome浏览器中对我的工作方式:
function callerName() {
return callerName.caller.name;
}
function foo() {
let myname = callerName();
// do something with it...
}
其他一些答案遇到了一些严格的javascript代码等问题。
我在这里看到的一些回答的组合。(已在FF,Chrome,IE11中测试)
function functionName()
{
var myName = functionName.caller.toString();
myName = myName.substr('function '.length);
myName = myName.substr(0, myName.indexOf('('));
return myName;
}
function randomFunction(){
var proof = "This proves that I found the name '" + functionName() + "'";
alert(proof);
}
调用randomFunction()将提醒包含函数名称的字符串。
JS小提琴演示:http://jsfiddle.net/mjgqfhbe/
可以在以下答案中找到对此的更新答案:https : //stackoverflow.com/a/2161470/632495
并且,如果您不想单击:
function test() {
var z = arguments.callee.name;
console.log(z);
}
信息为2016年的实际数据。
在歌剧中的结果
>>> (function func11 (){
... console.log(
... 'Function name:',
... arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
...
... (function func12 (){
... console.log('Function name:', arguments.callee.name)
... })();
Function name:, func11
Function name:, func12
结果在Chrome中
(function func11 (){
console.log(
'Function name:',
arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
})();
(function func12 (){
console.log('Function name:', arguments.callee.name)
})();
Function name: func11
Function name: func12
结果在NodeJS中
> (function func11 (){
... console.log(
..... 'Function name:',
..... arguments.callee.toString().match(/function\s+([_\w]+)/)[1])
... })();
Function name: func11
undefined
> (function func12 (){
... console.log('Function name:', arguments.callee.name)
... })();
Function name: func12
在Firefox中不起作用。在IE和Edge上未经测试。
结果在NodeJS中
> var func11 = function(){
... console.log('Function name:', arguments.callee.name)
... }; func11();
Function name: func11
结果在Chrome中
var func11 = function(){
console.log('Function name:', arguments.callee.name)
}; func11();
Function name: func11
在Firefox,Opera中不起作用。在IE和Edge上未经测试。
笔记:
~ $ google-chrome --version
Google Chrome 53.0.2785.116
~ $ opera --version
Opera 12.16 Build 1860 for Linux x86_64.
~ $ firefox --version
Mozilla Firefox 49.0
~ $ node
node nodejs
~ $ nodejs --version
v6.8.1
~ $ uname -a
Linux wlysenko-Aspire 3.13.0-37-generic #64-Ubuntu SMP Mon Sep 22 21:28:38 UTC 2014 x86_64 x86_64 x86_64 GNU/Linux
这是一个班轮:
arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '')
像这样:
function logChanges() {
let whoami = arguments.callee.toString().split('\n')[0].substr('function '.length).replace(/\(.*/, "").replace('\r', '');
console.log(whoami + ': just getting started.');
}
这是Igor Ostroumov答案的变体:
如果要将其用作参数的默认值,则需要考虑对“ caller”的第二级调用:
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
这将动态地允许在多个功能中实现可重用的实现。
function getFunctionsNameThatCalledThisFunction()
{
return getFunctionsNameThatCalledThisFunction.caller.caller.name;
}
function bar(myFunctionName = getFunctionsNameThatCalledThisFunction())
{
alert(myFunctionName);
}
// pops-up "foo"
function foo()
{
bar();
}
function crow()
{
bar();
}
foo();
crow();
如果您也想要文件名,以下是使用F-3000回答另一个问题的解决方案:
function getCurrentFileName()
{
let currentFilePath = document.scripts[document.scripts.length-1].src
let fileName = currentFilePath.split('/').pop() // formatted to the OP's preference
return fileName
}
function bar(fileName = getCurrentFileName(), myFunctionName = getFunctionsNameThatCalledThisFunction())
{
alert(fileName + ' : ' + myFunctionName);
}
// or even better: "myfile.js : foo"
function foo()
{
bar();
}