0

I want to do exactly the same as this question but use the function as a constructor.

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

> b = nameFunction('c', function () {})
[Function: c]
> typeof b
'function'

b is a function, yet it is not a constructor:

> new b()
Uncaught TypeError: b is not a constructor

If done in the standard way, it is a constructor:

> b = function() {}
[Function: b]
> new b()
b {}

But the name is b, not c.

How can I build a constructor with the given name and not using eval?

Gabriel Furstenheim
  • 2,969
  • 30
  • 27

2 Answers2

2

The answer provided by georg is correct but incomplete. In order to use the dynamically named function as a constructor, not only do you need to use an ordinary function but also you need to preserve the this context. We can do this by applying this and arguments to the body as follows.

function nameFunction(name, body) {
    const object = {
        [name]: function () {
            return body.apply(this, arguments);
        }
    };

    return object[name];
}

const Bar = nameFunction("Foo", function (foo) {
    this.foo = foo;
});

console.log(Bar.name, new Bar(42));
Aadit M Shah
  • 72,912
  • 30
  • 168
  • 299
1

Methods are not constructors (see https://262.ecma-international.org/7.0/#sec-functioncreate and https://262.ecma-international.org/7.0/#sec-functionallocate). Just define it as an ordinary function:

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

b = nameFunction('c', function () {})

new b
georg
  • 211,518
  • 52
  • 313
  • 390
  • I'm not sure this entirely works? `b = nameFunction('c', function () { this.x = 'x' }); new b() // Object { } <- no x property`? – evolutionxbox Mar 16 '21 at 21:17