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

IT技术 javascript oop
2021-02-01 00:40:07

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

// 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();
6个回答

如果你做这样的事情会起作用吗:

var myObject = window[classNameString];

..?

@JamesMcMahon 在那种情况下,您必须使用window[classNameString](args). 但正如 Crescent Fresh 提到的,要小心,因为这在某些情况下可能会中断。
2021-03-20 00:40:07
警告:这不适用于 ES6 类
2021-03-27 00:40:07
这似乎对我不起作用。经过一些试验和错误,我发现这有效: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
2021-03-31 00:40:07
认为你的意思window[classNameString](没有引号)。MyClass移动到较低(即function)范围时立即中断@kirk:是的,这是跨浏览器。
2021-04-04 00:40:07
如何使用此方法将参数传递给构造函数?
2021-04-11 00:40:07

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

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();
嗨,如何使用它并使其适用于导入的类?例如从'../../mazes/components/Grid'导入网格
2021-03-13 00:40:07
@JamesMcMahon:我们所知道的世界不再是现实。像nodejs这样的租户也来占领我们的星球了!:)
2021-03-27 00:40:07
由于严格模式已经出现(2009 年的ECMA-262 ed 5),如果不是由调用设置的(它不在示例中),则window || this可能在非浏览器环境中返回undefined
2021-03-28 00:40:07
为什么(windows || this),不是总是要定义窗口吗?
2021-04-08 00:40:07

顺便说一句: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 中如何获取全局对象?

@devios1 如果您测试代码,您会注意到它适用于任何上下文,而不仅仅是全局上下文。这就是为什么我们做Function('return this')()而不是return this. 前者自动切换到全局上下文。无论上下文如何,这都有效。window 可以被覆盖,并且只是浏览器。最好不知道代码执行上下文来编写跨平台代码。我给出的答案是跨平台的,不能被覆盖,因此比使用window. 它将在转译的代码中工作,如 webpack、gulp 和节点、扩展等。请先测试它。
2021-03-14 00:40:07
@Sebi,问题中没有任何地方暗示环境是客户端。此外,客户端也不一定意味着“浏览器”。答案提供了一种通过显式引用全局上下文来满足 OP 要求的方法 - 这就是重点。我指出,从全局上下文中引用全局上下文的唯一可靠方法是this,而不是window此外,不是从全局上下文中引用全局上下文的最可靠方法是top. 另外,将它注入到闭包中也许很好。
2021-03-19 00:40:07
就像答案所述,您所处的环境不一定是浏览器。因此,使用this更可取,因为在非浏览器环境中window可能未定义,或者不是您所期望的。
2021-03-28 00:40:07
@XedinUnknown 通常,当您编写一段 javascript 时,您知道它是用于客户端还是用于节点。如果你知道它是一个浏览器,那么就没有缺点喜欢windowthis
2021-03-30 00:40:07
this当从全局上下文调用时。window工作,无论您是在断章取义,所以我看不出有任何理由,更喜欢thiswindow
2021-04-11 00:40:07

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

var myObject = new window["MyClass"]();
这在所有浏览器中都有效吗?我看到一些帖子抱怨它对他们不起作用。
2021-03-30 00:40:07

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

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

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

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