119

I have this:

this.f = function instance(){};

I would like to have this:

this.f = function ["instance:" + a](){};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Totty.js
  • 15,563
  • 31
  • 103
  • 175
  • 14
    You can't. But you can have `this["instance"] = function() { }` – Raynos May 06 '11 at 00:14
  • 1
    see also [Is there any non-eval way to create a function with a runtime-determined name?](http://stackoverflow.com/q/9479046/1048572) – Bergi Apr 04 '15 at 21:26
  • 4
    To clarify what Raynos was saying, you can do `this["instance" + a] = function() { }`. That wasn't clear to me. – Andrew Sep 11 '19 at 20:03

24 Answers24

149

This will basically do it at the most simple level:

"use strict";
var name = "foo";
var func = new Function(
     "return function " + name + "(){ alert('sweet!')}"
)();

//call it, to test it
func();

If you want to get more fancy, I have a written an article on "Dynamic function names in JavaScript".

Marcosc
  • 3,101
  • 4
  • 17
  • 16
  • Nice work! I just discovered this on my own and was about to post it on one of these questions, but you beat me to it. I've been working a lot with backbone.js recently and am tired of seeing 'child' everywhere in my chrome debugger. This solves that issue. I wonder if there are any performance implications like using eval. – webXL Apr 12 '12 at 16:04
  • There are security implications as well. I get "The Function constructor is eval" from jsHint, so I'm wrapping this in a debug mode check, since that's the only reason to use this. I guess "use strict" will prevent any mucking with the global object, but any arguments to the Function constructor can be modified, and whatever 'this' is set to. – webXL Apr 17 '12 at 18:19
  • Yes, this for extreme situations where you need to construct something on the fly. – Marcosc Feb 13 '13 at 14:19
  • This is a nice solution. You can even _import_ variables from the surrounding scope like: `var a = "b", c = "d"; var name = "lorem"; var func = new Function("a", "c", "return function " + name + "(d) { return this.a = a; this.c = c; this.d = d }")();` – Halcyon Jan 19 '16 at 17:35
  • Here's a dynamic function that uses ECMAScript 2015 (ES6). I've used ES6's `const` (for immutability to prevent duplicate function names), an Arrow function (so `this` uses Window context when run in browser), and used an IIFE so it runs immediately in the browser: ```const a = 'foo'; (this.f = (() => new Function(`return function instance_${a}()\{ alert('called instance_${a}!') \}`)())())(); ``` – Luke Schoen Jan 29 '17 at 05:32
  • 2
    I honestly think https://stackoverflow.com/a/40918734/2911851 is a better solution, no need to include the body of the function as a string (unless I'm missing something, but I just tried and worked great). – Gian Franco Zabarino Aug 26 '17 at 20:10
  • Make sure the `name` does not have any whitespace: `name = "foo bar";`. – Константин Ван Oct 20 '17 at 09:46
  • 3
    [AirBnB strongly advises against this](https://github.com/airbnb/javascript#functions--constructor), as the Function constructor will use `eval` to evaluate the javascript - thus opening your code to a slew of vulnerabilities. – Philippe Hebert Oct 21 '17 at 01:27
  • 1
    Internal Server Error. your website is down =( – Matteo Jun 20 '19 at 04:22
66

You can use Object.defineProperty as noted in the MDN JavaScript Reference:

var myName = "myName";
var f = function () { return true; };
Object.defineProperty(f, 'name', {value: myName, writable: false});
Darren
  • 1,846
  • 15
  • 22
  • 3
    It appears this sets the name property as intended, yet if I log the function in my browser (latest Firefox dev edition) it prints `function fn()`, `fn` being the original name. Weird. – Kiara Grouwstra Nov 28 '17 at 20:41
  • same comment on google chrome evergreen. Property is properly set, but name in console, is the original name of the function. Cf. http://2ality.com/2015/09/function-names-es6.html#caveat-names-assigned-at-creation It seems that the name of the function is assigned at creation and cannot be changed? – user3743222 Mar 01 '18 at 02:54
  • On that 2ality.com page see the next paragraph "Changing the name of functions" [1] which describes the same technique found in the MDN Javascript Reference. 1. https://2ality.com/2015/09/function-names-es6.html#changing-the-names-of-functions – Darren Jul 08 '19 at 14:19
  • 1
    `writable: false` is not necessary because it already is non-writeable to begin with. – CherryDT Oct 06 '21 at 12:29
  • Still same in console: That's because what you see isn't based on the `name` but on the _source code_ of the function which is stored along with it - you can see it when you call `fn.toString()`. You can't change that. – CherryDT Oct 06 '21 at 12:31
57

In recent engines, you can do

function nameFunction(name, body) {
  return {[name](...args) {return body.apply(this, args)}}[name]
}



const x = nameFunction("wonderful function", (p) => p*2)
console.log(x(9)) // => 18
console.log(x.name) // => "wonderful function"

Thanks to T S for pointing out the need to preserve this in the comments.

Also, these days, I'd probably use the Object.defineProperty approach to achieve something similar.

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
kybernetikos
  • 8,281
  • 1
  • 46
  • 54
  • 11
    While this does work, I have started using `Object.defineProperty(func, 'name', {value: name})` in my own code, as I think it's maybe a little bit more natural and understandable. – kybernetikos Jun 30 '17 at 14:56
  • does it work with transpiled code? (Babel or typescript outputs) – Hitmands Sep 04 '17 at 15:07
  • 1
    This works for me! I cannot understand the syntax though; can you please explain it? I believe I understand it all except the two uses of `[name]`, and the fact that the `return` creates a function without the `function` keyword. – Jason Young May 08 '19 at 18:01
  • 5
    Answering my own question: `{[expr]: val}` is an object initializer (as is a JSON object) where `expr` is some expression; whatever it evaluates to is the key. `{myFn (..){..} }` is shorthand for `{myFn: function myFn(..){..} }`. Note that `function myFn(..) {..}` can be used as an expression just like an anonymous function, only `myFn` would have a name. The last `[name]` is just accessing the member of the object (just like `obj.key` or `obj['key']`). `...` is the spread operator. (Main source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) – Jason Young May 09 '19 at 00:22
  • And as others have pointed out, a function expression which a variable, `const`, or object property is assigned to takes the name of that variable, `const`, or object property. Syntactic position and all that. – Jason Young May 09 '19 at 00:30
  • 6
    Thanks for your sollution! Note: This doesn't preserve the value of `this`. For example `obj={x:7,getX(){return this.x}}; obj.getX=nameFunction('name',obj.getX); obj.getX();` won't work. You could edit your answer and use `function nameFunction(name, body) { return {[name](...args) {return body.apply(this, args)}}[name] }` instead! – T S Aug 07 '19 at 22:41
  • 4
    While this works in console and node.js, it does not work when transpiled, in my case with typescript 3.6.2. – Qwerty Oct 17 '19 at 12:13
  • @JasonYoung thanks for detailed comment mate, helped a lot! – godblessstrawberry Oct 28 '19 at 18:26
21

Update 2021: CherryDT's answer should be the easiest most straight forward way now, but it doesn't work consistently with different browsers for stack traces or Function.prototype.toString(), so if you need that you're stuck with this less convenient solution.

Old answer: Many suggestions here are suboptimal, by using eval, hacky solutions or wrappers. As of ES2015 names are inferred from the syntactic position for variables and properties.

So this will work just fine:

const name = 'myFn';
const fn = {[name]: function() {}}[name];
fn.name // 'myFn'

Resist the temptation to create named function factory methods as you wouldn't be able to pass the function from outside and retrofit it into the syntactic position to infer its name. Then it's already too late. If you really need that, you have to create a wrapper. Someone did that here, but that solution doesn't work for classes (which are also functions).

A much more in-depth answer with all the variants outlined has been written here: https://stackoverflow.com/a/9479081/633921

Albin
  • 2,410
  • 2
  • 29
  • 27
  • 1
    How does this answer improve https://stackoverflow.com/a/41854075/3966682? – d4nyll Sep 05 '18 at 15:22
  • 1
    @d4nyll I've already answered that: It creates a wrapper, which breaks stateful functions (functions using "this") aka classes. – Albin Sep 05 '18 at 18:12
  • 1
    @CherryDT Sorry, I had to go back and revisit some old use cases to realize what the problem was. `Object.defineProperty` was in part lacking support in Safari for a long time (and Safari browser versions were kept alive longer than most browsers due to being shipped with hardware), but mostly that it doesn't work consistently for stack traces and `Function.prototype.toString`. With your solution, try this `const fn1 = nameFunction('fn2', function fn3(){ throw new Error("whoops") }); fn1();` and check the stack trace in Firefox vs Chrome (if you remove fn3 they still behave different). – Albin Oct 06 '21 at 17:58
12

As others mentioned, this is not the fastest nor most recommended solution. Marcosc's solution below is the way to go.

You can use eval:

var code = "this.f = function " + instance + "() {...}";
eval(code);
isherwood
  • 58,414
  • 16
  • 114
  • 157
Mo Valipour
  • 13,286
  • 12
  • 61
  • 87
  • 6
    I know this is what the OP asked for, but this is a horrible idea. Just because you can does not mean you should do something like this. There a much better alternatives that are almost exactly the same functionality-wise. – Thomas Eding May 06 '11 at 03:07
  • 1
    this is really important at debugging. in my case shows me directly the name of the class... so it's helpfull. – Totty.js Jan 11 '12 at 12:15
  • 4
    @sg3s: can you propose another solution? – Tom Jul 30 '12 at 16:58
  • @Tom I didn't need to, Marcosc already had a non-eval solution at the time I downvoted this, and please don't think it was meant unfriendly, I could have just downvoted but it is suggested to at least let someone know why they were downvoted :) – sg3s Jul 30 '12 at 22:20
  • 2
    @sg3s: Thanks for answering my comment! Let me explain what I meant, and what I actually want to ask: is Marcosc's solution really significantly different from eval? Does it really make a difference if you eval something or feed it to the Function constructor? If so, can you explain the difference and its ramifications? Thanks! – Tom Jul 31 '12 at 05:04
  • 6
    @Tom For future readers: this solution is not really different from Marcosc's answer, they both use `eval()` (the `Function` constructor does that inside). – kapa Mar 23 '15 at 10:17
  • 1
    I don't believe this should be the accepted answer. ES's new computed property name would be the best way to accomplish this. See kybernetikos' answer. – Levi Roberts Jun 11 '17 at 09:37
  • 1
    #1 - Why is this the accepted answer if everyone agrees it is not the way to go? #2 - When the code runs, the method does not exist. I get an error is undefined. – Taersious Dec 03 '18 at 16:32
4

For setting the name of an existing anonymous function (based on Marcosc's answer):

var anonymous = function() { return true; }

var name = 'someName';
var strFn = anonymous.toString().replace('function ', 'return function ' + name);
var fn = new Function(strFn)();

console.log(fn()); // —> true

Demo.

Note: Don't do it ;/

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Onur Yıldırım
  • 32,327
  • 12
  • 84
  • 98
  • When you downvote it's ok. But you should give the courtesy of your reasoning so we can learn from you. OP asks for "dynamic" function names. This is one way to do it, but I'd never recommend nor did I ever do it. – Onur Yıldırım Sep 06 '18 at 20:22
  • The only solution, that actually worked for my case. And there are no worries about all the uglyness, cause the function finally re-compiles and executes on the GPU, yet leaving some freedom for naming function in GPU kernel differently from it's JS counerpart. Thanks for your effort. – Denis Golovkin Mar 03 '23 at 12:31
4

The function's name property by default isn't writeable, but since it's configurable we can still use Object.defineProperty to change it. Since Object.defineProperty conveniently returns the object itself, we can write a function with a dynamic name like this:

const theName = 'foobar'

const fn = Object.defineProperty(function () {
  /* ... */
}, 'name', { value: theName })

console.log(fn.name) // Logs foobar

Of course this could be factored out into a helper function:

const nameFunction = (name, fn) => Object.defineProperty(fn, 'name', { value: name })

const fn = nameFunction('foobar', function () {
  /* ... */
})

console.log(fn.name) // Logs foobar

The above nameFunction function can also be used to rename an existing function, of course (here it's just renaming and returning the anonymous one).

CherryDT
  • 25,571
  • 5
  • 49
  • 74
3

The Marcosc's answer has got already defined [String] function body. I was looking for the solution to rename already declared function's name and finally after an hour of struggling I've dealt with it. It:

  • takes the alredy declared function
  • parses it to [String] with .toString() method
  • then overwrites the name (of named function) or appends the new one (when anonymous) between function and (
  • then creates the new renamed function with new Function() constructor

function nameAppender(name,fun){
  const reg = /^(function)(?:\s*|\s+([A-Za-z0-9_$]+)\s*)(\()/;
  return (new Function(`return ${fun.toString().replace(reg,`$1 ${name}$3`)}`))();
}

//WORK FOR ALREADY NAMED FUNCTIONS:
function hello(name){
  console.log('hello ' + name);
}

//rename the 'hello' function
var greeting = nameAppender('Greeting', hello); 

console.log(greeting); //function Greeting(name){...}


//WORK FOR ANONYMOUS FUNCTIONS:
//give the name for the anonymous function
var count = nameAppender('Count',function(x,y){ 
  this.x = x;
  this.y = y;
  this.area = x*y;
}); 

console.log(count); //function Count(x,y){...}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Paweł
  • 4,238
  • 4
  • 21
  • 40
3

What about

this.f = window["instance:" + a] = function(){};

The only drawback is that the function in its toSource method wouldn't indicate a name. That's usually only a problem for debuggers.

entonio
  • 2,143
  • 1
  • 17
  • 27
  • that is not good because the only reason I need is to see faster the name of the Classes. Every class in my system is an anonymous function and in the debugger shows me anonymous.. – Totty.js Jan 11 '12 at 12:17
  • 3
    Well, then you could have said that in the question. – entonio Jan 18 '12 at 16:02
3

The syntax function[i](){} implies an object with property values that are functions, function[], indexed by the name, [i].
Thus
{"f:1":function(){}, "f:2":function(){}, "f:A":function(){}, ... } ["f:"+i].

{"f:1":function f1(){}, "f:2":function f2(){}, "f:A":function fA(){}} ["f:"+i] will preserve function name identification. See notes below regarding :.

So,

javascript: alert(
  new function(a){
    this.f={"instance:1":function(){}, "instance:A":function(){}} ["instance:"+a]
  }("A") . toSource()
);

displays ({f:(function () {})}) in FireFox.
(This is almost the same idea as this solution, only it uses a generic object and no longer directly populates the window object with the functions.)

This method explicitly populates the environment with instance:x.

javascript: alert(
  new function(a){
    this.f=eval("instance:"+a+"="+function(){})
  }("A") . toSource()
);
alert(eval("instance:A"));

displays

({f:(function () {})})

and

function () {
}

Though the property function f references an anonymous function and not instance:x, this method avoids several problems with this solution.

javascript: alert(
  new function(a){
    eval("this.f=function instance"+a+"(){}")
  }("A") . toSource()
);
alert(instanceA);    /* is undefined outside the object context */

displays only

({f:(function instanceA() {})})
  • The embedded : makes the javascript function instance:a(){} invalid.
  • Instead of a reference, the function's actual text definition is parsed and interpreted by eval.

The following is not necessarily problematic,

  • The instanceA function is not directly available for use as instanceA()

and so is much more consistent with the original problem context.

Given these considerations,

this.f = {"instance:1": function instance1(){},
          "instance:2": function instance2(){},
          "instance:A": function instanceA(){},
          "instance:Z": function instanceZ(){}
         } [ "instance:" + a ]

maintains the global computing environment with the semantics and syntax of the OP example as much as possible.

Community
  • 1
  • 1
Ekim
  • 949
  • 1
  • 8
  • 9
  • This resolution only works for static names or with ES6 dynamic property names. For example `(name => ({[name]:function(){}})[name])('test')` works but `(name => {var x={}; x[name] = function(){}; return x[name];})('test')` doesn't – William Leung Oct 30 '17 at 04:58
2

Dynamic methods of an object may be created using Object Literal Extensions provided by ECMAScript 2015 (ES6):

const postfixes = ['foo', 'bar'];

const mainObj = {};

const makeDynamic = (postfix) => {
  const newMethodName = 'instance: ' + postfix;
  const tempObj = {
    [newMethodName]() {
      console.log(`called method ${newMethodName}`);
    }
  }
  Object.assign(mainObj, tempObj);
  return mainObj[newMethodName]();
}

const processPostfixes = (postfixes) => { 
  for (const postfix of postfixes) {
    makeDynamic(postfix); 
  }
};

processPostfixes(postfixes);

console.log(mainObj);

The output of running the code above is:

"called method instance: foo"
"called method instance: bar"
Object {
  "instance: bar": [Function anonymous],
  "instance: foo": [Function anonymous]
}
Luke Schoen
  • 4,129
  • 2
  • 27
  • 25
2

The best way is to create an object with the list of dynamic functions, like:

const USER = 'user';

const userModule = {
  [USER + 'Action'] : function () { ... }, 
  [USER + 'OnClickHandler'] : function () { ... }, 
  [USER + 'OnCreateHook'] : function () { ... }, 
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
аlex
  • 5,426
  • 1
  • 29
  • 38
1

There are two methods to achieve this, and they have their pros and cons.


name property definition

Defining immutable name property of a function.

Pros

  • Every character is available for the name. (eg. () 全 {}/1/얏호/ :D #GO(@*#%! /*)

Cons

  • The function's syntactic (“expressional”) name may not correspond with its name property value.

Function expression evaluation

Making a named function expression and evaluating it with Function constructor.

Pros

  • The function's syntactic (“expressional”) name always corresponds with its name property value.

Cons

  • Whitespaces (and etc.) are not available for the name.
  • Expression-injectable (eg. For input (){}/1//, the expression is return function (){}/1//() {}, gives NaN instead of a function.).

const demoeval = expr => (new Function(`return ${expr}`))();

// `name` property definition
const method1 = func_name => {
    const anon_func = function() {};
    Object.defineProperty(anon_func, "name", {value: func_name, writable: false});
    return anon_func;
};

const test11 = method1("DEF_PROP"); // No whitespace
console.log("DEF_PROP?", test11.name); // "DEF_PROP"
console.log("DEF_PROP?", demoeval(test11.toString()).name); // ""

const test12 = method1("DEF PROP"); // Whitespace
console.log("DEF PROP?", test12.name); // "DEF PROP"
console.log("DEF PROP?", demoeval(test12.toString()).name); // ""

// Function expression evaluation
const method2 = func_name => demoeval(`function ${func_name}() {}`);

const test21 = method2("EVAL_EXPR"); // No whitespace
console.log("EVAL_EXPR?", test21.name); // "EVAL_EXPR"
console.log("EVAL_EXPR?", demoeval(test21.toString()).name); // "EVAL_EXPR"

const test22 = method2("EVAL EXPR"); // Uncaught SyntaxError: Unexpected identifier
1

If you want to have a dynamic function like the __call function in PHP, you could use Proxies.

const target = {};

const handler = {
  get: function (target, name) {
    return (myArg) => {
      return new Promise(resolve => setTimeout(() => resolve('some' + myArg), 600))
    }
  }
};

const proxy = new Proxy(target, handler);

(async function() {
  const result = await proxy.foo('string')
  console.log('result', result) // 'result somestring' after 600 ms
})()
blablabla
  • 1,468
  • 15
  • 17
1

You can use Dynamic Function Name and parameters like this.

1) Define function Separate and call it

let functionName = "testFunction";
let param = {"param1":1 , "param2":2};

var func = new Function(
   "return " + functionName 
)();

func(param);

function testFunction(params){
   alert(params.param1);
}

2) Define function code dynamic

let functionName = "testFunction(params)";
let param = {"param1":"1" , "param2":"2"};
let functionBody = "{ alert(params.param1)}";

var func = new Function(
    "return function " + functionName + functionBody 
)();

func(param);
0

Building on Marcosc's answer, if you want to rename any function, use this:

// Returns the function named with the passed name
function namedFunction(name, fn) {
    return new Function('fn',
        "return function " + name + "(){ return fn.apply(this,arguments)}"
    )(fn)
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
B T
  • 57,525
  • 34
  • 189
  • 207
0

This utility function merges multiple functions into one (using a custom name). The only requirement is that provided the functions are properly "new lined" at the start and end of its scope.

const createFn = function(name, functions, strict=false) {

    var cr = `\n`, a = [ 'return function ' + name + '(p) {' ];

    for(var i=0, j=functions.length; i<j; i++) {
        var str = functions[i].toString();
        var s = str.indexOf(cr) + 1;
        a.push(str.substr(s, str.lastIndexOf(cr) - s));
    }
    if(strict == true) {
        a.unshift('\"use strict\";' + cr)
    }
    return new Function(a.join(cr) + cr + '}')();
}

// Test
var a = function(p) {
    console.log("this is from a");
}
var b = function(p) {
    console.log("this is from b");
}
var c = function(p) {
    console.log("p == " + p);
}

var abc = createFn('aGreatName', [a, b, c])

console.log(abc) // Output: function aGreatName()

abc(123)

Output

this is from a
this is from b
p == 123
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
MetalGodwin
  • 3,784
  • 2
  • 17
  • 14
0

I had better luck in combining Darren's answer and kyernetikos's answer.

const nameFunction = function (fn, name) {
  return Object.defineProperty(fn, 'name', {value: name, configurable: true});
};

/* __________________________________________________________________________ */

let myFunc = function oldName () {};

console.log(myFunc.name); // oldName

myFunc = nameFunction(myFunc, 'newName');

console.log(myFunc.name); // newName

Note: configurable is set to true to match the standard ES2015 spec for Function.name1

This especially helped in getting around an error in Webpack similar to this one.

Update: I was thinking of publishing this as an npm package, but this package from sindresorhus does exactly the same thing.

  1. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/name
Scott Rudiger
  • 1,224
  • 12
  • 16
0

I struggled a lot with this issue. Albin's solution worked like a charm while developing, but it did not work when I changed it to production. After some debugging, I realized how to achieve what I needed. I'm using ES6 with CRA (create-react-app), which means it's bundled by Webpack.

Let’s say you have a file that exports the functions you need:

myFunctions.js

export function setItem(params) {
  // ...
}

export function setUser(params) {
  // ...
}

export function setPost(params) {
  // ...
}

export function setReply(params) {
  // ...
}

And you need to dynamically call these functions elsewhere:

myApiCalls.js

import * as myFunctions from 'path_to/myFunctions';
/* note that myFunctions is imported as an array,
 * which means its elements can be easily accessed
 * using an index. You can console.log(myFunctions).
 */

function accessMyFunctions(res) {
  // lets say it receives an API response
  if (res.status === 200 && res.data) {
    const { data } = res;
    // I want to read all properties in data object and
    // call a function based on properties names.
    for (const key in data) {
      if (data.hasOwnProperty(key)) {
        // you can skip some properties that are usually embedded in
        // a normal response
        if (key !== 'success' && key !== 'msg') {
          // I'm using a function to capitalize the key, which is
          // used to dynamically create the function's name I need.
          // Note that it does not create the function, it's just a
          // way to access the desired index on myFunctions array.
          const name = `set${capitalizeFirstLetter(key)}`;
          // surround it with try/catch, otherwise all unexpected properties in
          // data object will break your code.
          try {
            // finally, use it.
            myFunctions[name](data[key]);
          } catch (error) {
            console.log(name, 'does not exist');
            console.log(error);
          }
        }
      }
    }
  }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Rodrigo M.
  • 21
  • 1
  • 5
0

Node.js JavaScript Class Based Dynamic Function Name

File: Schema.js

class Schema {
  constructor() {
    this.name = null;
  }

  virtual(name = null) {
    this.name = name;
    return this;
  }

  get(func = false) {
    if (!this.name || !func instanceof Function) {
      throw new Error("Name and function must be provided.");
    }
    // Attach the dynamic function name to the "this" Object
    this[this.name] = func;
    this.name = null;
  }
}

module.exports = Schema;

File: index.js

const Schema = require("./Schema.js");

const User = new Schema();

User.virtual("getPostCount").get(() => {
  return 10 + 10;
});

const ok = User.getPostCount();
console.log({ User });
console.log(ok);
Jason
  • 813
  • 11
  • 13
-1
function myFunction() {
    console.log('It works!');
}

var name = 'myFunction';

window[name].call();
Danilo Colasso
  • 2,360
  • 17
  • 11
-2

I might be missing the obvious here, but what's wrong with just adding the name? Functions are invoked regardless of their name. Names are just used for scoping reasons. If you assign it to a variable, and it's in scope, it can be called. That happens if you are executing a variable which happens to be a function.

If you must have a name for identification reasons when debugging, insert it between the keyword function and the opening brace.

var namedFunction = function namedFunction (a,b) {return a+b};

alert(namedFunction(1,2));
alert(namedFunction.name);
alert(namedFunction.toString());

An alternative approach is to wrap the function in an outer renamed shim, which you can also pass into an outer wrapper, if you don't want to dirty the surrounding namespace. If you want to actually dynamically create the function from strings (which most of these examples do), it's trivial to rename the source to do what you want.

If, however, you want to rename existing functions without affecting their functionality when called elsewhere, a shim is the only way to achieve it.

(function(renamedFunction) {

  alert(renamedFunction(1,2));
  alert(renamedFunction.name);
  alert(renamedFunction.toString());
  alert(renamedFunction.apply(this,[1,2]));


})(function renamedFunction(){return namedFunction.apply(this,arguments);});

function namedFunction(a,b){return a+b};
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
cestmoi
  • 11
  • 1
  • Function / method `name` is useful as it's inferred from variable and properties now. It's also used in stack traces. Ex `var fn = function(){}; console.log(fn.name)`. It's immutable, so you can't change it later. If you write a factory method that names all functions `fn` then this will make debugging harder. – Albin Feb 20 '18 at 20:21
  • Calculated functions have no useful name, e.g. `function compose(f, g) { return (x) => f(g(x)); }; const process = compose(uppercase, compose(stripSpaces, renderToJSON));`. Stack traces won't have names for the `process` function or the `compose(stripSpaces, renderToJSON)` function. Adding a name in `compose`, e.g. `return function composed(x) { ... }`, doesn't tell us which function it's referring to. Refactoring those two functions causes repetition, boilerplate, etc. and loses all higher-order structure in a mess of fiddly first-order implementation details. – Warbo Jan 26 '21 at 10:33
-3

You was near:

this["instance_" + a] = function () {...};

{...};

berge
  • 31
  • 2
-9

This is best solution, better than new Function('return function name(){}')().

Eval is the fastest solution:

Enter image description here

var name = 'FuncName'
var func = eval("(function " + name + "(){})")
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Maxmaxmaximus
  • 2,098
  • 1
  • 19
  • 17
  • Anyone who is reading this, follow follow follow this answer. – Maxmaxmaximus Dec 01 '16 at 04:32
  • 2
    @majidarif the guy is correct, it is fastest: https://jsperf.com/dynamicfunctionnames/1. Is by far not the safest though. – Sancarn Sep 15 '18 at 08:44
  • Please review *[Why not upload images of code/errors when asking a question?](https://meta.stackoverflow.com/questions/285551/)* (e.g., *"Images should only be used to illustrate problems that* ***can't be made clear in any other way,*** *such as to provide screenshots of a user interface."*) and [do the right thing](https://stackoverflow.com/posts/38227395/edit) (it covers answers as well). Thanks in advance. – Peter Mortensen Apr 16 '23 at 15:30