1

I currently have the following working code:

Function.prototype.GetLastCallerName = function () {
  if (!this.arguments || !this.arguments.callee || !this.arguments.callee.caller) return null;
  var result = /^function\s+([\w\$]+)\s*\(/.exec(this.arguments.callee.caller.toString());
  this.LastCaller = result ? result[1] : 'Anonymous';
  return this.LastCaller;
};

I picked up that code from another thread. As you can see, it extends the Function.prototype in order to add a method called GetLastCallerName, which picks the last calling function name and (1) sets it to LastCaller on Function.LastCaller and (2) returns it.

In order to make it work:

function MyFunction1() {
  MyFunction1.GetLastCallerName();
  console.log(MyFunction.LastCaller);
}

function MyFunction2() { 
  MyFunction1(); 
}

MyFunction2();

What I'd like to be able to do: Eliminate the need to use GetLastCallerName() every time and extend Function in order to perform that get every time any function is called.

scniro
  • 16,844
  • 8
  • 62
  • 106
Arnie
  • 212
  • 1
  • 2
  • 11
  • 5
    ...but why would you want to do this? – zzzzBov Nov 13 '17 at 14:17
  • 1
    On **any** function? Nope, can't do it in ES5. (You could in ES2015+, but only by doing some Really Horrible Things to `Function.prototype` (or individually to functions, as a one-off) -- and it would still fail in strict mode like `GetLastCallerName` does). Moreover, you **shouldn't** do it. :-) (And shouldn't do the `GetLastCallerName` thing either – T.J. Crowder Nov 13 '17 at 14:17
  • 1
    It it not recommended to modify the prototype of native objects. Instead, create an object that inherits from Function and modify that. – Scott Marcus Nov 13 '17 at 14:17
  • You are also not following proper casing conventions for functions. – Scott Marcus Nov 13 '17 at 14:19
  • 1
    Plus even this code won't work in strict mode. Hello `arguments .callee`. – dfsq Nov 13 '17 at 14:19
  • @ScottMarcus: Thank you for your reply... I understand what you're saying and you're right, but this is the only way (for the moment) I've found functional, with the minimal amount of code, to resolve my need. It simply works, but it depends on having to call that method everytime. – Arnie Nov 13 '17 at 14:22
  • All good comment, thank you so much for them...gosh, is there any way I can then achieve this? (getting the last calling function's name) – Arnie Nov 13 '17 at 14:24
  • @Arnie were you able to make any forward progress on this? Was my answer below able to point you in the right direction? Please share some feedback as I'd like to help you solve this! – scniro Nov 14 '17 at 14:17
  • @scniro: My sincere apologies for replying so late! I'm from Puerto Rico and hurricane Maria left us in very bad shape. All communications were down for quite some time and I haven't had the opportunity to log back in. As to your question: yes, your answer did partially help. Problem is that I couldn't use ES6 classes in the project I was working on, so I was looking for a way to achieve the same without using them. The GetLastCaller() extension was only intended for debugging purposes, but finding a way to achieve what I was looking for would prove helpful in the future ;-) Thank you! – Arnie Jul 03 '18 at 00:47

1 Answers1

1

I'm struggling to follow what you have tried so far with your example, but I think I get the idea of what you'd like to do. Why not leverage classes, and extend on them for your use case. Check out the following example...

class Base {

  baseFn() {
    console.log('from base');
  }
}

class Thing extends Base {

  fn1() {
    this.baseFn();
  }
}

let thingee = new Thing();

thingee.fn1();

So baseFn is now always called when fn1 is called.

JSFiddle Link - class demo


In some of your comments it looks like you are wanting to get the "last calling function's name." How about passing back the instance of the caller itself to the parent? This would surely give you even more flexibility because now you can sculpt your caller however you wish. Check out the following...

class Base {

  baseFn(caller) {
    console.log(caller.id); // 1
  }
}

class Thing extends Base {

  constructor(id) {
    super();

    this.id = id;
  }

  fn1() {
    this.baseFn(this);
  }
}

let thingee = new Thing('1');

thingee.fn1();

Now you can add whatever you'd like to your Thing instance, in this case, an object with an id of 1 which can be inspected when fn1 propagates up to baseFn

JSFiddle Link - caller demo

scniro
  • 16,844
  • 8
  • 62
  • 106