0

I have a situation in which I need at some point in my application the name of the constructor

instance.constructor.name

However, when I create the constructor I have its name stored in a variable. So, to give you an idea of what I want

var nameOfTheFunction = "Test" ;
var BarFoo = function() { /* do stuff */ } ;
BarFoo.name = nameOfTheFunction ;

This of course doesn't work, because the name property is read-only.

So is it possible to dynamically create a constructor function with the end result that the instances it creates will have

instance.constructor.name === nameOfTheFunction

UPDATE: checkout my comment below, because it does what I was looking for. For this questions though, thanks to the answer, I initially was looking for this

(new Function( 'base', 'return function ' + Foo.name + '(){ base.apply(this, arguments); };'))(Foo) ;

The problem with this solution is that the thing created here isn't an instanceof Foo, except when you do something like this, which brought me to the solution in my comment below!

Jeanluca Scaljeri
  • 26,343
  • 56
  • 205
  • 333

3 Answers3

1

I don't think eval is such a bad idea. But I would recommend, using a factory function, so you don't have to write all the code of your function in string literals:

function createNamedFunction(name, func) {
    eval("var f = function " + name + "(){return func.apply(this, arguments);};");
    return f;
}

var t = createNamedFunction("myFunc", function () {
    console.log("hello");
});

console.log(t.name);  //myFunc
t();  //hello

FIDDLE

EDIT

You could also manipulate the string representation of your function directly, so you don't have to use the apply method:

function createNamedFunction(name, func) {
    var fstr = func.toString(),
        index = fstr.indexOf("(");
    fstr = "function " + name + fstr.substring(index);
    eval("var f = " + fstr + ";");
    return f;
}
basilikum
  • 10,378
  • 5
  • 45
  • 58
  • do you think 'eval' should be used instead of 'new Function(){..}' ? – Jeanluca Scaljeri Aug 12 '13 at 14:17
  • 2
    The reason is here @Jeanluca Scaljeri: Note: Functions created with the Function constructor do not create closures to their creation contexts; they always run in the window context (unless the function body starts with a "use strict"; statement, in which case the context is undefined). From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function – Khanh TO Aug 12 '13 at 14:31
  • 2
    @JeanlucaScaljeri I'm not sure how `new Function(){...}` would help you. As far as I know, it doesn't allow you to specify a name? – basilikum Aug 12 '13 at 14:36
0

In your case, I think we could use eval

var nameOfTheFunction = "Test" ;
var BarFoo = eval("function " + nameOfTheFunction + "() { /* do stuff */ }") ;
Khanh TO
  • 48,509
  • 13
  • 99
  • 115
  • Eval is NOT a good solution ! DON'T USE EVAL ! It's not safe. – m_vdbeek Aug 12 '13 at 13:55
  • @AwakeZoldiek "It's not safe" isn't a related reason here. Either explain what you mean, or give a better reason – Ian Aug 12 '13 at 13:57
  • Eval is a security issue because you are executing untrusted source code. If an attacker could modify the parameters used in the string concatenation, they could execute malicious code in a users browser and run exploits, steal cookies ...etc. – m_vdbeek Aug 12 '13 at 13:59
  • 2
    @AwakeZoldiek `eval` is no more dangerous than your browser's console/developer tools. And who said anything about "untrusted" source code? – Ian Aug 12 '13 at 14:05
0

If you are on the browser side, you could use the following solution :

Javascript: Dynamic function names

Of course this would make your function a global variable.

EDIT: If you absolutely want to use eval, you can use the following construct :

function generateFunction(functionName) {
    function __REPLACE__() {
        // your function's code
    }
    eval(__REPLACE__.toString().replace('__REPLACE__', functionName));
    return functionName;
}
Community
  • 1
  • 1
m_vdbeek
  • 3,704
  • 7
  • 46
  • 77
  • Thnx for the link! I think that 'new Function' is better than 'eval'. Why do you think it makes global variables ? var Constr = new Function(){ 'return function' + name + '(){}'; } – Jeanluca Scaljeri Aug 12 '13 at 14:15
  • If you declare a function as a property of Window, every object that has access to window (which is everything) has your function as a variable in his scope. You're right that `new Function()` is better than `eval()`. – m_vdbeek Aug 12 '13 at 14:18
  • With the second solution I wrote, you can write your function as a normal JavaScript function and than pass it as an argument to `generateFunction()`. – m_vdbeek Aug 12 '13 at 14:19
  • 3
    Note: Functions created with the Function constructor do not create closures to their creation contexts; they always run in the window context (unless the function body starts with a "use strict"; statement, in which case the context is undefined). From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function – Khanh TO Aug 12 '13 at 14:26