JavaScript中的动态实例化[Classname as String]

Dynamic instantiation in JavaScript [Classname as String]

本文关键字:Classname as String 实例化 动态 JavaScript      更新时间:2023-09-26

我正在使用JSON格式的Javascript和Appdescriptor。我想做的是创建一个类的实例,其中类名保存为oModelConf[sModelName].type中的字符串。如果不是这样的话,我想服用"sap.ui.model.odata.ODataModel"

相关问题提供此解决方案:

function instantiate(className, args) {
    var o, f, c;
    c = window[className]; // get reference to class constructor function
    f = function(){}; // dummy function
    f.prototype = c.prototype; // reference same prototype
    o = new f(); // instantiate dummy function to copy prototype properties
    c.apply(o, args); // call class constructor, supplying new object as context
    o.constructor = c; // assign correct constructor (not f)
    return o;
}

我认为这不是一个很好的解决方案。

EDIT它对我不起作用,因为我的类没有在窗口上定义,所以window[className]是未定义的。我不知道SAPUI5 中在哪里定义了我的函数

第二种解决方案:

eval(`a = new ${oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel"}(sServiceUrl, true);`);

这不是一个更好的解决方案,因为我们不应该使用eval()

有更好的解决方案吗

编辑2由于pimskies答案中的url,我找到了另一个解决方案:

由于window.sap.ui.model.odata.ODataModelsap.ui.model.odata.ODataModel相同,window.sapwindow[sap]相同我可以取我的字符串,用][替换所有的.,把右括号放在前面和后面。

我不会编写代码,因为这不是一个持续的解决方案。(我不应该也对eval进行编码…)

您可以使用jQuery.sap.getObject访问类:

var ModelClass = jQuery.sap.getObject(oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel");
var model = new ModelClass();

编辑:另一种方式(如果你使用AMD,我会推荐)

如果您使用的是现代AMD模块,但不知道包含类的模块是否已经加载,则应该使用sap.ui.require()异步加载模块。它要求通过其统一的资源名称指定模块(转换可能是最丑陋的部分):

var className = oModelConf[sModelName].type || "sap.ui.model.odata.ODataModel";
var urn = className.replace(".", "/"); //Convert to unified resource name
sap.ui.require([urn],function(ModelClass){
  //This function is called when the module is available
  var model = new ModelClass();
  ...
});

也许可以将字符串映射到一个类?

function Foo() {
  console.log('new foo');
}
function Bar() {
  console.log('new bar');
}
var objects = {
    'foo': Foo,
  'bar': Bar
};
var cls = objects.foo || Bar;
new cls();

https://jsfiddle.net/ckd56d9v/1/

或者看看这个答案:https://stackoverflow.com/a/9804142/5930258

为什么不把两者结合起来?由于window[className]出现故障,请将其替换为oModelConf[className].type || sap.ui.model.odata.ODataModel。。。

function instantiate(className, args) {
    var o, f, c;
    c = oModelConf[className] || sap.ui.model.odata.ODataModel;
    f = function(){}; // dummy function
    f.prototype = c.prototype; // reference same prototype
    o = new f(); // instantiate dummy function to copy prototype properties
    c.apply(o, args); // call class constructor, supplying new object as context
    o.constructor = c; // assign correct constructor (not f)
    return o;
}