Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript new object instance from dynamic function name

In PHP a string can be used to dynamically select a class for instantiation. Here are 2 simple classes in PHP:

<?php
class Magic implements Genius {
  public function perform() {
    echo 'madya look :P' . PHP_EOL;
  }
}

class Genie implements Genius {
  public function perform() {
    echo 'your wish has been granted!' . PHP_EOL;
  }
}

Now there could be a variable such that the class instantiated at runtime is based upon its contents

$sGeniusClass = 'Magic';
$oGenius      = new $sGeniusClass();

Now in Javascript I like to use functions as constructors to have some level of typed-ness, in that vein I might have:

function Magic() {}
Magic.prototype = {
  perform : function()
  {
    console.log('madya look :P');
  }
}

function Genie() {}
Genie.prototype = {
  perform : function()
  {
    console.log('your wish has been granted!');
  }
}

I know I can pull off something similar to PHP with an eval:

Approach #1

var sClassName = 'Genie';
eval('var oGenius = new ' + sClassName);

I've also seen an approach that makes a call to the Function function:

Approach #2

var sClassName = 'Genie';
var oGenius = new Function('return new ' + sClassName)();

On the MDN though it sounds like this suffers performance from re-evaluation every time an instance is created:

Function objects created with the Function constructor are parsed when the function is created. This is less efficient than declaring a function and calling it within your code, because functions declared with the function statement are parsed with the rest of the code.

Now I have one more approach that is a bit tedious:

Approach #3

var aClassMap = {
  Magic : Magic,
  Genie : Genie,
  create : function(sClassName) {
    if(this[sClassName] === undefined)
      return false;
    return new this[sClassName];
  }
}

var sClassName = 'Genie';
var oGenius = aClassMap.create(sClassName);

It seems to be my favorite overall, no use of eval, and no subsequent re-evaluation, like solution #2. It's still a bit of work though, so my question, twofold:

  1. Are there any other ways to do this other than the 3 approaches I've shown?
  2. Is there something similar to PHP where a string can map to a function to be instantiated?
like image 455
quickshiftin Avatar asked Oct 08 '22 17:10

quickshiftin


1 Answers

I think you covered them all. You can simplify your 3rd approach, however, by remembering that global variables and functions are properties of the window object, so you can create global classes using window, like this:

var myClassName = "Genie";
window[myClassName] = function {};
window[myClassName].prototype = {
  perform : function()
  {
    console.log('I am a ' + myClassName + ', and your wish has been granted!');
  }
}

I think performance will be as good as always (since Javascript uses hash tables internally to reference object properties, no matter what).

like image 72
Diego Avatar answered Oct 18 '22 11:10

Diego