Jamie Hutber
Jamie Hutber

Reputation: 28076

How do you find out the caller function in JavaScript when use strict is enabled?

Is it possible to see the callee/caller of a function when use strict is enabled?

'use strict';

function jamie (){
    console.info(arguments.callee.caller.name);
    //this will output the below error
    //uncaught TypeError: 'caller', 'callee', and 'arguments' properties may not be accessed on strict mode functions or the arguments objects for calls to them
};

function jiminyCricket (){
   jamie();
}

jiminyCricket ();

Upvotes: 59

Views: 51504

Answers (6)

Geth44
Geth44

Reputation: 1

Another writing :

function fnCaller() {
    let res = [...(new Error().stack).matchAll(/([#$_A-Z0-9].+)@|at ([#$_A-Z0-9]+) \(/gi)];
    return res.length > 2 ? res[2][1] || res[2][2] : null; // null if function called directly from script
}

Also in same way for getting function name :

    function fnName() {
    let res = [...(new Error().stack).matchAll(/([#$_A-Z0-9].+)@|at ([#$_A-Z0-9]+) \(/gi)];
    return res[1][1] || res[1][2];
}

Upvotes: 0

inetphantom
inetphantom

Reputation: 2594

Please note that this should not be used in production. This is an ugly solution, which can be helpful for debugging, but if you need something from the caller, pass it as argument or save it into a accessible variable.

The short version of @p.s.w.g answer(without throwing an error, just instantiating one):

    let re = /([^(]+)@|at ([^(]+) \(/g;
    let aRegexResult = re.exec(new Error().stack);
    sCallerName = aRegexResult[1] || aRegexResult[2];

Full Snippet:

'use strict'

function jamie (){
    var sCallerName;
    {
        let re = /([^(]+)@|at ([^(]+) \(/g;
        let aRegexResult = re.exec(new Error().stack);
        sCallerName = aRegexResult[1] || aRegexResult[2];
    }
    console.log(sCallerName);
};

function jiminyCricket(){
   jamie();
};

jiminyCricket(); // jiminyCricket

Upvotes: 36

toddmo
toddmo

Reputation: 22416

  functionName() {
    return new Error().stack.match(/ at (\S+)/g)[1].get(/ at (.+)/);
  }

  // Get - extract regex
  String.prototype.get = function(pattern, defaultValue = "") {
    if(pattern.test(this)) {
      var match = this.match(pattern);
      return match[1] || match[0];
    }
    return defaultValue; // if nothing is found, the answer is known, so it's not null
  }

Upvotes: -1

Larry
Larry

Reputation: 1248

You can get a stack trace using:

console.trace()

but this is likely not useful if you need to do something with the caller.

See https://developer.mozilla.org/en-US/docs/Web/API/Console/trace

Upvotes: 7

p.s.w.g
p.s.w.g

Reputation: 149020

For what it's worth, I agree with the comments above. For whatever problem you're trying to solve, there are usually better solutions.

However, just for illustrative purposes, here's one (very ugly) solution:

'use strict'

function jamie (){
    var callerName;
    try { throw new Error(); }
    catch (e) { 
        var re = /(\w+)@|at (\w+) \(/g, st = e.stack, m;
        re.exec(st), m = re.exec(st);
        callerName = m[1] || m[2];
    }
    console.log(callerName);
};

function jiminyCricket (){
   jamie();
}

jiminyCricket(); // jiminyCricket

I've only tested this in Chrome, Firefox, and IE11, so your mileage may vary.

Upvotes: 54

Benamar
Benamar

Reputation: 905

It does not worked for me Here is what I finally do, just in case it helps someone

function callerName() {
  try {
    throw new Error();
  }
  catch (e) {
    try {
      return e.stack.split('at ')[3].split(' ')[0];
    } catch (e) {
      return '';
    }
  }

}
function currentFunction(){
  let whoCallMe = callerName();
  console.log(whoCallMe);
}

Upvotes: 12

Related Questions