web-dev-qa-db-fra.com

Comment créer un objet JavaScript à l'aide d'une chaîne variable pour définir le nom de la classe?

Voici ce que j'essaie de faire - c'est du pseudo-code et cela ne fonctionne pas. Quelqu'un sait-il comment y parvenir pour de vrai:

// Define the class
MyClass = Class.extend({});

// Store the class name in a string
var classNameString = 'MyClass';

// Instantiate the object using the class name string
var myObject = new classNameString();
64
Kirk Ouimet

Cela fonctionnerait-il si vous faisiez quelque chose comme ceci:

var myObject = window[classNameString];

..?

59
peirix

Voici une solution plus robuste qui fonctionnera avec des fonctions à espace de noms:

var stringToFunction = function(str) {
  var arr = str.split(".");

  var fn = (window || this);
  for (var i = 0, len = arr.length; i < len; i++) {
    fn = fn[arr[i]];
  }

  if (typeof fn !== "function") {
    throw new Error("function not found");
  }

  return  fn;
};

Exemple:

my = {};
my.namespaced = {};
(my.namespaced.MyClass = function() {
  console.log("constructed");
}).prototype = {
  do: function() {
    console.log("doing");
  }
};

var MyClass = stringToFunction("my.namespaced.MyClass");
var instance = new MyClass();
instance.do();
55
Yuriy Nemtsov

BTW: window est la référence à l'objet global dans le navigateur JavaScript. Qui est également this, et devrait fonctionner même dans des environnements sans navigateur tels que Node.js, Chrome, code transpilé, etc.

var obj = new this[classNameString]();

La limitation est que la classe appelée doit être dans le contexte global. Si vous souhaitez appliquer la même chose à une classe de portée, vous devez faire:

var obj = (Function('return new ' + classNameString))()

Cependant, il n'y a vraiment aucune raison d'utiliser une chaîne. Les fonctions JavaScript sont elles-mêmes des objets, tout comme les chaînes qui sont également des objets.

Modifier

Voici une meilleure façon d'obtenir la portée globale qui fonctionne en mode strict ainsi que dans les environnements JS sans navigateur:

var global;
try {
  global = Function('return this')() || (42, eval)('this');
} catch(e) {
  global = window;
}

// and then
var obj = new global[classNameString]

De: Comment obtenir l'objet global en JavaScript?

28
bucabay

Si MyClass est global, vous pouvez y accéder en tant que propriété d'un objet window (en supposant que votre code s'exécute dans un navigateur) en utilisant la notation en indice.

var myObject = new window["MyClass"]();
11
Chetan Sastry

Si classNameString provient d'une source sécurisée, vous pouvez utiliser

var classNameString = 'MyClass';
var myObject = eval("new " + classNameString + "()");

Cette solution fonctionne avec des espaces de noms et est indépendante de la plateforme (navigateur/serveur).

4
Misaz

Voici une version améliorée de la méthode de Yuriy qui gère également les objets.

var stringToObject = function(str, type) {
    type = type || "object";  // can pass "function"
    var arr = str.split(".");

    var fn = (window || this);
    for (var i = 0, len = arr.length; i < len; i++) {
        fn = fn[arr[i]];
    }
    if (typeof fn !== type) {
        throw new Error(type +" not found: " + str);
    }

    return  fn;
};
3
pjesi