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


76

这就是我想要做的-这是伪代码,不起作用。有谁知道如何真正做到这一点:

// 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();

Answers:


66

如果您这样做是可行的:

var myObject = window[classNameString];

..?


那行得通。peirix,您真棒。您认为它与跨浏览器兼容吗?
柯克·奥伊梅特

1
认为你的意思window[classNameString](没有引号)。一旦MyClass移至较低function范围(即),即会中断。@kirk:是的,这是跨浏览器。

1
如何使用此方法将参数传递给构造函数?
詹姆斯·麦克马洪

3
@JamesMcMahon在这种情况下,您必须使用window[classNameString](args)。但是,正如Crescent Fresh所述,要小心,因为在某些情况下这可能会中断。
peirix 2012年

8
这似乎不适用于我。经过一番尝试和错误后,我发现此方法有效:var obj = new Home(id);,但此方法无效:var obj = new window["Home"](id);。我正在尝试使其工作:new window[x](id);在哪里x = "Home"……我得到的错误是Uncaught TypeError: window[x] is not a constructor
亚伯拉罕·穆尔西亚诺·本扎登

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;
};

例:

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();

为什么(windows || this),不总是要定义窗口吗?
詹姆斯·麦克马洪

11
@JamesMcMahon:我们所知道的世界不再是现实。像nodejs这样的租户也开始占领我们的星球!:)
Mrchief

由于严格的模式具有沿到来(ECMA-262编5,2009年),window || this可以返回未定义在非浏览器环境,如果不是由呼叫(它是不是在示例)设置。
RobG

嗨,如何使用此功能,并使它适用于导入的类?例如,从“ ../../mazes/components/Grid”导入网格
preston

33

顺便说一句:window是浏览器JavaScript中对全局对象的引用。这也是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]

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


9
只有this从全局上下文调用它。window无论您所处的环境如何,它都能正常工作,因此我认为没有理由thiswindow
devios1 2011年

4
像答案状态一样,您所处的环境不一定是浏览器。因此,this首选使用,因为在非浏览器环境中window可能未定义或未定义。
XedinUnknown

@XedinUnknown通常,当您编写一段JavaScript时,您会知道它是用于客户端还是假设用于节点。如果你知道它是一个浏览器,那么就没有缺点喜欢windowthis
塞比

2
@Sebi,问题的任何地方都没有暗示环境是客户端。同样,客户端也不一定表示“浏览器”。答案提供了一种通过明确引用全局上下文来满足OP要求的方法-这就是重点。我要指出,从全局上下文引用全局上下文的唯一可靠方法this不是window。此外,不是从全局上下文引用全局上下文的最可靠方法是top。同样,将它注入到封闭中可能也很好。
XedinUnknown

1
@ devios1如果您测试代码,您会发现它可以在任何上下文中工作,而不仅仅是全局上下文。这就是为什么我们做Function('return this')()的不是return this。前者自动切换到全局上下文。无论上下文如何,这都有效。窗口可以被覆盖,并且仅用于浏览器。最好不知道代码执行上下文来编写跨平台代码。我给出的答案是跨平台的,无法覆盖,因此比使用更好window。它可以在已编译的代码中工作,例如与webpack,gulp以及在节点,扩展等中一起使用。请先对其进行测试。
bucabay '17

12

如果MyClass是全局的,则可以使用下标符号将其作为窗口对象的属性(假设您的代码在浏览器中运行)进行访问。

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

这在所有浏览器中都有效吗?我看到一些帖子抱怨这对他们不起作用。
PHP Guru

9

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

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

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


3
我不知道,也不知道为什么删除它?
Misaz

1
@Jacksonkr,这是否也意味着我不应该首先喝啤酒,因为它可能会成为一种坏习惯?:)
文斯·霍斯特

3
打个比方:eval听到一个坏主意,就用它就像喝醉了一样。“什么也没发生……………………我上次开车…………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………… 别那样
杰克森克尔

7
提倡永远不要使用eval或其他函数,这是个坏建议。如果它是一个没有任何用例的功能,那么现在它已被折旧并删除为功能。
MacroMan '18

1
确实是MacroMan。删除它作为答案是荒谬的。

3

这是Yuriy方法的改进版本,该方法还可以处理对象。

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;
};

0
function myClass(arg){
}

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

var instance=new dynamic_class(arg); // OK

0

在Firefox上,扩展有安全性规则,而Javascript控制台也有安全性规则。不要犯我在控制台中测试的错误,因为这些解决方案都不起作用。而当您从页面进行测试时,效果更好:

  • 评估解决方案效果很好
  • Function('return new'...可以工作(创建对象),除了构造函数的参数作为“ undefined”传递外,我没有测试其他解决方案。

法语:Sur Firefox il ya desrèglesdesécuritéqui的附加辅助扩展,以及控制台Javascript。新的解决方案和市场的解决方案。在德累斯顿大学页面上的同等学历:

  • 溶液解决方案
  • Function('return new'... fonctionne(l'objet estcréé)sauf que lesparamètresdu constructioneur sont“ undefined” Je n'ai pastestéles autres解决方案。
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.