如何使用变量String创建JavaScript对象来定义类名?

Kir*_*met 65 javascript oop

这是我正在尝试做的 - 这是伪代码,不起作用.有谁知道如何实现这一目标:

// 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();
Run Code Online (Sandbox Code Playgroud)

pei*_*rix 61

如果你做了这样的事情,它会工作:

var myObject = window[classNameString];
Run Code Online (Sandbox Code Playgroud)

..?

  • 这对我来说似乎没有用.经过一些试验和错误后,我发现这有效:`var obj = new Home(id);`,但这不是:`var obj = new window ["Home"](id);`.我试图让它工作:`new window [x](id);`where`x ="Home"`...我得到的错误是`Uncaught TypeError:window [x]不是构造函数` (6认同)
  • @JamesMcMahon在这种情况下你必须使用`window [classNameString](args)`.但正如Crescent Fresh提到的那样,要小心,因为在某些情况下这可能会破裂. (3认同)
  • 警告:这[不适用于 ES6 类](/sf/answers/4761188841/)。 (3认同)

Yur*_*sov 56

这是一个更强大的解决方案,可以使用命名空间函数:

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;
};
Run Code Online (Sandbox Code Playgroud)

例:

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();
Run Code Online (Sandbox Code Playgroud)

  • @JamesMcMahon:我们所知道的世界不再是现实.像nodejs这样的租户也占据了我们的星球!:) (11认同)

buc*_*bay 29

BTW:window是浏览器JavaScript中对全局Object的引用.这也是this,甚至应该在非浏览器环境中工作,例如Node.js,Chrome扩展,转换代码等.

var obj = new this[classNameString]();

限制是被调用的类必须在全局上下文中.如果要将其应用于作用域类,则需要执行以下操作:

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

但是,确实没有理由使用字符串.JavaScript函数本身就是对象,就像字符串一样也是对象.

编辑

这是获得在严格模式和非浏览器JS环境中工作的全局范围的更好方法:

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

// and then
var obj = new global[classNameString]
Run Code Online (Sandbox Code Playgroud)

来自:如何在JavaScript中获取全局对象?

  • 如果从全球范围调用,它只是"这个".无论你在上下文中,`window`都有效,所以我认为没有理由比`window`更喜欢`this`. (9认同)
  • 与答案状态一样,您所处的环境不一定是浏览器.因此,使用`this`是首选,因为在非浏览器环境中,`window`可能未定义,或者不是您所期望的. (3认同)
  • @Sebi,问题中的任何地方都没有暗示环境是客户端。同样,客户端也不一定意味着“浏览器”。答案提供了一种通过明确引用全局上下文来满足OP要求的方法-这就是重点。我要指出的是,从全局上下文引用全局上下文的唯一可靠方法是“ this”而不是“ window”。此外,不是从全局上下文引用全局上下文的最可靠方法是“ top”。同样,将其注入到封闭中可能也很好。 (2认同)

Che*_*try 11

如果MyClass是全局的,您可以使用下标表示法将其作为window对象的属性(假设您的代码在浏览器中运行)进行访问.

var myObject = new window["MyClass"]();
Run Code Online (Sandbox Code Playgroud)


Mis*_*saz 9

如果classNameString来自安全来源,您可以使用

var classNameString = 'MyClass';
var myObject = eval("new " + classNameString + "()");
Run Code Online (Sandbox Code Playgroud)

此解决方案适用于命名空间并且独立于平台(浏览器/服务器)。

  • 提倡永远不要使用函数,无论是 eval 还是其他,都是不好的建议。如果它是一个没有任何用例的功能,那么它现在已经被贬低并作为一项功能删除了。 (8认同)
  • 我不知道它,也不知道为什么它被删除了? (3认同)
  • 根据您的类比:当您听说这是一个坏主意时使用 `eval` 就像酒后驾车一样。“什么都没发生......呃......上次我开车喝酒......呃......实际上我喝醉了开车更好!......呃......” 当出现问题时已经太晚了。不要成为那个人。 (3认同)
  • @Jacksonkr,这是否也意味着我一开始就不应该喝啤酒,因为这可能会成为一个坏习惯?:) (2认同)

Tec*_*ist 8

浏览器全局对象是window,每当您使用 定义全局变量var或使用 函数时function,您都会将它们添加到 中window。因此你可以在那里得到你的“类”定义:

var args = [];
var className = 'MyClass';
var obj = new window[className](args);
Run Code Online (Sandbox Code Playgroud)

但这不适用于 ES6 类声明

使用 ES6 关键字声明的类class根据标准进行不同的处理。

用 声明的类class MyClass { }定义了一个全局类,该类不会成为window全局对象的属性。换句话说,以下内容适用

class MyClass {};
typeof window.MyClass === 'undefined';
Run Code Online (Sandbox Code Playgroud)

那么,如何对 ES6 类执行同样的操作呢?需要对象访问符号,因为这是解析字符串名称所需的,但要搜索的父对象不再可用。

一种方法是创建您自己的上下文对象,在那里声明您的类并在那里搜索它。在代码中:

// this variable actually goes in `window`
var classes = {};
// declare class inside
classes.MyClass = class {
   // the class code
};

var args = [];
var className = 'MyClass';
var obj = new classes[className](args); // dynamic for "new classes.MyClass(args)"
Run Code Online (Sandbox Code Playgroud)


Xak*_*iru 5

function myClass(arg){
}

var str="myClass";
dynamic_class=eval(str);

var instance=new dynamic_class(arg); // OK
Run Code Online (Sandbox Code Playgroud)

编辑:内联示例

function Person(name){
    this.name=name;
}
var person1=new (eval("Person"))("joe");
Run Code Online (Sandbox Code Playgroud)