3

In JavaScript, is it possible for a function to return its own function call as a string?

function getOwnFunctionCall(){
    //return the function call as a string, based on the parameters that are given to the function.
}

I want this function to simply return its own function call as a string (if it's even possible to do this):

var theString = getOwnFunctionCall(5, "3", /(a|b|c)/);
//This function call should simply return the string "getOwnFunctionCall(5, \"3\", "\/(a|b|c)\/")".
5
  • 4
    What would you do with parameters that are instances of complex objects? Commented May 1, 2013 at 18:53
  • 1
    No. Is there something in particular you're trying to do? Commented May 1, 2013 at 18:53
  • @sciritai I've been trying to find ways to prevent specific functions in eval statements from being evaluated, and this is one potential solution for that problem. Commented May 1, 2013 at 18:56
  • 1
    @AndersonGreen Sanitizing JavaScript is very hard if not theoretically impossible without executing it before. Commented May 1, 2013 at 18:59
  • Whenever I see "Is [blank] possible" questions I am tempted to give a one-word answer: "yes." Most technical questions have possible solutions. If you really want someone to show how to accomplish the task, perhaps a "how to" question would be better in the future. Commented May 1, 2013 at 19:03

6 Answers 6

2

I put this one up on jsFiddle: http://jsfiddle.net/pGXgh/.

function getOwnFunctionCall() {
    var result = "getOwnFunctionCall(";
    for (var i=0; i < arguments.length; i++) {
        var isString = (toString.call(arguments[i]) == '[object String]');
        var quote = (isString) ? "\"" : "";
        result += ((i > 0) ? ", " : "");
        result += (quote + arguments[i] + quote);
    }
    return result + ")";
}

alert(getOwnFunctionCall(5, "3", /(a|b|c)/));

Note that this should work for your example, but still needs work for arbitrarily complex objects/JSON included as a parameter.

Sign up to request clarification or add additional context in comments.

2 Comments

This function works properly when strings, regular expressions, and numbers are used as parameters. However, when a function is used as a parameter, it prints the source of the function instead of the function's name. I'll see if I can fix this.
Yes, you would definitely need special cases for formatting each object type. And if an object is passed, do you want the variable name of the original object?
2

http://jsfiddle.net/WkJE9/4/

function DisplayMyName() 
{
   //Convert function arguments into a real array then let's convert those arguments to a string.
   var args = [].slice.call(arguments).join(',');

   // Get Function name
   var myName = arguments.callee.toString();
   myName = myName.substr('function '.length);
   myName = myName.substr(0, myName.indexOf('('));

   return(myName + " ("+ args + ")"); 
}

var functionText = DisplayMyName(5, "3", /(a|b|c)/) //returns DisplayMyName(5, "3", /(a|b|c)/)
alert(functionText);

2 Comments

This doesn't work when a function is used as a parameter: jsfiddle.net/WkJE9/2
Returns the native code for alert....you shouldn't be assigning a value to the variable alert for a parameter anyways.
1

Using the implicit arguments variable, you can extract both the function arguments and the function name:

function getOwnFunctionCall() {
    var args = arguments; // Contains the arguments as an array
    var callee = arguments.callee; // The caller function
    // Use this to construct your string
}

Edit

Several comments note that callee is not something to be relied on. But if this is something you are going to do inside each of your methods, then just use the function name as you have defined it:

var functionName = "getOwnFunctionCall"; // But you can really just use it inline...

2 Comments

This will fail in strict mode. Callee is no longer a valid property of the arguments object. developer.mozilla.org/en-US/docs/JavaScript/Reference/…
It should be noted that arguments.callee is not allowed in strict mode and is frowned upon by the spec writers. developer.mozilla.org/en-US/docs/JavaScript/Reference/…
1

if you NEED to do it, and need to do it in global strict, and you don't want to hard-code the names:

function args(arg){
 var me;
  try{ badCAll654(); }catch(y){  me=String(y.stack).split("args")[1].split("\n")[1].trim().split("@")[0].replace(/^at /,"").split(" ")[0].trim() }
  return  me +"("+[].slice.call(arg).join(", ")+")";
}



function getOwnFunctionCall() {
  "use strict";
  return args(arguments);
}


getOwnFunctionCall(1,true, /dd/);

this can be a good debugging tool, but i would not recommend using it on production sites/apps; it's going to impact performance quite a bit. This pattern only works in chrome and firefox, but works under a global "use strict".

IE9 is less strict, so you can do the following:

function args(arg){
 var me=arg.callee+'';
  return  me.split("(")[0].split("function")[1].trim() +"("+[].slice.call(arg).join(", ")+")";
}   

function getOwnFunctionCall() {
  "use strict";
  return args(arguments);
}


getOwnFunctionCall(1,true, /dd/);

if you poly-fill the trim()s, it should also work in IE8. if you don't use strict, you can do even more cool stuff like log the function that called the function that's being logged. you CAN even rip that function's source to find calls to the logged function if you want the names of the arguments and not just the values. Complex and worthless, but possible.

again, you should really use this only for debugging!

Comments

0

Based on your comment

I've been trying to find ways to prevent specific functions in eval statements from being evaluated, and this is one potential solution for that problem.

What you are asking for might not be what you really need. Why not just override the functions you want to prevent before evaling and restore them aferwards:

var blacklist = [ 'alert', 'setTimeout' ];

var old = {};

// Save the blacklisted functions and overwrite
blacklist.forEach(function(name) {
    old[name] = window[name];
    window[name] = function() {
        console.log(name + ' has been disabled for security reasons');
    }
});

eval('alert("Hello world")');

// restore the original functions
blacklist.forEach(function(name) {
    window[name] = old[name];
});

1 Comment

why remove them? just make them empty privates. ex: function(code){ var alert,prompt; eval(code) }
0

is it possible for a function to return its own function call as a string?

No. You cannot extract by what expression you got your arguments into the function - you can only access their values. Of course you could simulate a call string with primitive values, but you never know whether they were passed to the function as a variable, a literal, or a whole expression.

Maybe, Mozilla's toSource method can help you with that.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.