我想做的是这样的——这只是伪代码,无法正常工作。有没有人知道如何真正实现:
// 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();
我想做的是这样的——这只是伪代码,无法正常工作。有没有人知道如何真正实现:
// 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();
如果你这样做,会起作用吗:
var myObject = window[classNameString];
很抱歉,我只能够用英文进行回答。这里有一个更健壮的解决方案,可以与命名空间函数一起使用:
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)
,window 不是一直都会被定义吗? - James McMahon顺便提一句:在浏览器JavaScript中,window是指全局对象。它也是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]
this
。而 window
则不管你处于哪个上下文中都可以使用,因此我认为没有理由优先选择 this
而不是 window
。 - devios1window
可能未定义或与你预期的不同,使用this
更为可取。 - XedinUnknownthis
,而不是window
。
此外,从全局上下文引用最可靠的方式可能是 top
。
同时,将其注入到闭包中也可能是一个好的选择。 - XedinUnknownFunction('return this')()
而不是 return this
。前者会自动切换到全局上下文。这种方法可以在任何上下文中工作,而且 window 可以被覆盖,只适用于浏览器。不知道代码执行上下文来编写跨平台代码是很好的。我给出的答案是跨平台的,不能被覆盖,因此比使用 window
更好。它可以在转译代码中工作,例如 webpack、gulp 和 node、扩展等。请先进行测试。 - bucabaywindow
是相同的,但没有 window
的问题。调用上下文可以是任何作用域。 - bucabay如果 MyClass 是全局的,你可以使用下标符号作为 window 对象的一个属性来访问它(假设你的代码在浏览器中运行)。
var myObject = new window["MyClass"]();
classNameString
是来自安全来源,您可以使用。var classNameString = 'MyClass';
var myObject = eval("new " + classNameString + "()");
这个解决方案使用命名空间,与平台(浏览器/服务器)无关。
eval
不好时,却仍然使用它就像是酒后驾车。"上次我喝酒开车没事发生...嗝...事实上我喝醉了开车反而开得更好! ...嗝..." 等到出了问题再想避免已经太迟了。不要成为那样的人。 - Jacksonkr浏览器全局对象是window
,每当您使用var
定义全局变量或使用function
定义函数时,都会将它们添加到window
中。
因此,您可以在那里获取您的“类”定义:
var args = [];
var className = 'MyClass';
var obj = new window[className](args);
window
全局对象的属性。换句话说,以下内容适用:class MyClass {};
typeof window.MyClass === 'undefined';
// 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)"
function myClass(arg){
}
var str="myClass";
dynamic_class=eval(str);
var instance=new dynamic_class(arg); // OK
编辑:内联示例
function Person(name){
this.name=name;
}
var person1=new (eval("Person"))("joe");
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;
};
这个有效:
import { Class1 } from './profiles/class1.js'
import { Class2 } from './profiles/class2.js'
let profiles = {
Class1,
Class2
}
let profileAsString = 'Class1'
new profiles[profileAsString]()
在我的情况下,我正在从服务器预加载数据,并尝试使用类加载预加载的数据(特别是,我正在使用vuex-orm)。我选择了一个模型列表,并将它们映射到我已经在文件顶部导入的类,而不是采用任何超级花哨的东西。请看以下示例:
import Video from '@models/Video'
import Purchase from '@models/Purchase'
let modelClassMap = {
'Video': Video,
'Purchase': Purchase,
}
Object.entries(preload.models).forEach(entry => {
const [modelName, modelData] = entry
if(modelClassMap[modelName]){
modelClassMap[modelName].insertOrUpdate({data: modelData})
}
})
明确、安全、简单。不错!
window [classNameString]
(不带引号)。只要将MyClass
移动到较低的范围(即function
),它就会中断。@kirk:是的,这是跨浏览器的。 - Crescent Freshwindow[classNameString](args)
。但正如Crescent Fresh所提到的那样,要小心,因为在某些情况下可能会出现错误。 - peirixvar obj = new Home(id);
,但是这个不行:var obj = new window["Home"](id);
。我正试图让这个工作:new window[x](id);
其中x = "Home"
... 我得到的错误是Uncaught TypeError: window[x] is not a constructor
。 - Abraham Murciano Benzadon