DEV Community

Bruce Axtens
Bruce Axtens

Posted on

Applying the callee's name aka self-referential functions

Apparently there are some things that one may do with the arguments vector that are frowned up. This may be about one of those things.

One can find out the name of the function that one is in at runtime.

function calleeName(a) {
  return a.callee
    .toString()
    .split(" ")[1]
    .split("(")[0]
    .trim();
};
Enter fullscreen mode Exit fullscreen mode

Pass in arguments as the parameter and receive the name of the function that one is calling from. Caveat: this only works with functions defined using function and not with const. Also, anonymous functions will return an empty string.

Example

function Bruce() {
    console.log(calleeName(arguments));
}

Bruce();
Enter fullscreen mode Exit fullscreen mode

This displays Bruce on the console.

Before we get to the most interesting thing, here is a support function which I use from time to time when generating small bits of HTML or XML (and which I need later in the demonstration), tag().

function tag(a, b, c) {
  return "undefined" === typeof c ? 
    "<" + a + ">" + (null === b ? "" : b.toString()) + "</" + a + ">" :
    "<" + a + " " + b.toString() + ">" + 
      (null === c ? "" : c.toString()) + "</" + a + ">";
}
Enter fullscreen mode Exit fullscreen mode

Originally there was an if in there but after the Closure Compiler finished with it, it became a complex ternary boolean ? true : false. a gets the XML/HTML tagname. b is the data to wrap. However, if c is defined then it is assumed to be the data and b is assumed to be an attribute to put after the a.

Now we come to the focal point. Below we have some functions that are named after XML markup: xml, staff and vehicle. Instead of coding the name of the markup into the body of the function, we let calleeName retrieve it from the arguments vector and unshift it into a copy of arguments and then .apply that to the tag function.

function xml() {
  var args = [].slice.call(arguments);
  args.unshift(calleeName(arguments));
  return tag.apply(this, args);
}

function staff() {
  var args = [].slice.call(arguments);
  args.unshift(calleeName(arguments));
  return tag.apply(this, args);
}

function vehicle() {
  var args = [].slice.call(arguments);
  args.unshift(calleeName(arguments));
  return tag.apply(this, args);
}
Enter fullscreen mode Exit fullscreen mode

Notice that the body of each of these functions is exactly the same yet the output from each is different. xml() will output a <xml></xml> with data and optional attributes etc.

So that all gets used like this:

var Staff = staff("id='BRUAXT' age='58' languages='English,Tok Pisin,Urdu'", "Bruce");
var Vehicle = vehicle("id='BRUAXT'", "bicycle");
var Xml = xml(Staff + Vehicle);
console.log(Xml);
Enter fullscreen mode Exit fullscreen mode

which outputs

<xml><staff id='BRUAXT' age='58' languages='English,Tok Pisin,Urdu'>Bruce</staff><vehicle id='BRUAXT'>bicycle</vehicle></xml>
Enter fullscreen mode Exit fullscreen mode

While I don't have a use for that right now, it is interesting and I can think of some possible applications. Maybe you can too.

Top comments (0)