1

Given this method:

var obj = {}, obj.foo = function () {};

Is it possible to assign the method a name after it's created so it looks similar to:

var obj = {}, obj.bar = function bar() {};

The foo method is anonymous and assigned to a property. The bar method is named and assigned to a property.

Can you turn the anonymous foo method into a named foo method dynamically? Is there a property on the function object which can be set or something similar to:

obj.foo.<name> = Object.keys(obj)[0];

Without using jquery, please. Also, this is in a node server application so cross browser issues won't matter.

EDIT: The answer that worked for me is Daniel's link: How to dynamically set a function/object name in Javascript as it is displayed in Chrome. This approach also handles parameters for the function.

Community
  • 1
  • 1
ciso
  • 2,887
  • 6
  • 33
  • 58
  • 2
    Why do you need such functionality? –  Apr 04 '15 at 17:30
  • There's no way to do that unless you're willing to get the string value of the function (that is, its JavaScript source code), modify that, and then make a new function from it. What are you trying to accomplish? The name given in a `function` expression like that isn't visible outside the function anyway. – Pointy Apr 04 '15 at 17:30
  • possible duplicate of [Naming an anonymous function](http://stackoverflow.com/questions/3854141/naming-an-anonymous-function) – Pascal Ockert Apr 04 '15 at 17:32
  • @ChrisGciso not really; there may be references to the original function in various places. – Pointy Apr 04 '15 at 17:38
  • 2
    http://stackoverflow.com/questions/5871040/how-to-dynamically-set-a-function-object-name-in-javascript-as-it-is-displayed-i – Daniel Conde Marin Apr 04 '15 at 17:53
  • Why do you need a function name, if you have filename and line number? I don't know about you, but I simply look at where the code is located when looking at stacktraces and then jump to the source with two editor shortcuts: 1) Jump to file + 2) Go to line. – Domi Apr 04 '15 at 18:11
  • You can simply override your function's `toString` method in that case. And you can streamline the process, by e.g. creating an object with anonymous functions (the keys being the names), then iterate over all of them and set their `toString` correspondingly. Alternatively, use [`sourceUrl`](https://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/) or wait until [displayName](http://www.thecssninja.com/javascript/source-mapping#toc-sourceurl) is supported. – Domi Apr 04 '15 at 18:23
  • possible duplicate of [Dynamic function name in javascript?](http://stackoverflow.com/questions/5905492/dynamic-function-name-in-javascript) – Marco Bonelli Apr 04 '15 at 23:35

2 Answers2

1

You cannot renane that precise instance of your anonymous function, but you can use a closure to redefine it changing its name, like this:

var obj = {};

// Anonymous function
obj.foo = function() {/* whatever */};

// Renaming...
obj.foo = (function(fn) {
    return function foo() {
        return fn.apply(this, arguments);
    }
})(obj.foo);

// Now try in the console:
obj.foo
> function foo() {
    return fn.apply(this, arguments);
}
Marco Bonelli
  • 63,369
  • 21
  • 118
  • 128
0

Summarizing the two solutions found in other posts referenced above:

1) Dynamic function name in javascript?

2) How to dynamically set a function/object name in Javascript as it is displayed in Chrome

var foo, bar, name = "bar", renameFunction;

foo = function () {return "baz";}
bar = foo;
console.log(bar.name + " /  " + bar()); //  / baz;

//*************** Solution #1 **********************************************
renameFunction = function (name, fn) {
    return (new Function("noName", "return function " + name + 
        "(){ return noName() };")(fn));
}
bar = renameFunction(name, foo);
console.log(bar.name + " /  " + bar()); // bar / baz;

//*************** Solution #2 **********************************************
renameFunction = function (name, fn) {
    return (new Function("return function (call) {return function " + name +
        " () { return call(this, arguments) }; };")())(Function.apply.bind(fn));
};   
bar = renameFunction(name, foo);
console.log(bar.name + " /  " + bar()); // bar / baz;

They both work. The second solution is more complex, but I'm not sure yet what it adds.

UPDATE: The 2nd solution is the better one. It can handle arguments to the function which the first solution does not.

Community
  • 1
  • 1
ciso
  • 2,887
  • 6
  • 33
  • 58