JS动态创建函数

IT技术 javascript
2021-02-19 03:05:07

我正在为 JS 游戏创建 AI 引擎,它由有限状态机组成。我正在从 XML 加载状态数及其变量值。我也想加载行为,因为我没有时间创建脚本语言,我认为将 JS 代码“插入”外部文件(在 XML 节点内)并在要求。

类似的东西

<evilguy1>
    <behaviour>
        this.x++;
    </behaviour>
    <behaviour>
        this.y++;
    </behaviour>
</evilguy1>

像这样的事情:

function behaviour_1(){
    this.x++;
}
function behaviour_2(){
    this.y++;
}

我的问题是,既然我已经加载了代码,我该如何执行它?我想为每个代码“节点”创建一个具有唯一名称的函数,然后从游戏逻辑中调用它们,但我不知道这是否可行(因为您可以从 HTML 加载更多 JS 代码,您也应该能够从 JS 代码中做到这一点,不是吗?)。如果没有,有没有类似的解决方案?提前致谢!

(PS:越少依赖外部库越好)

编辑1:

好的,现在我知道如何创建包含代码的函数了

window[classname] = function() { ... };
4个回答

好吧,你可以使用Function构造函数,就像在这个例子中一样:

var f = new Function('name', 'return alert("hello, " + name + "!");');
f('erick');

通过这种方式,您定义了一个带有参数和主体的新函数,并将其分配给变量 f。您可以使用哈希集并存储许多函数:

var fs = [];
fs['f1'] = new Function('name', 'return alert("hello, " + name + "!");');
fs['f1']('erick');

加载 xml 取决于它是在浏览器还是服务器上运行。

这是不推荐的方法,您应该避免使用它,因为它会导致性能问题。有关更多信息,请参阅You don't know JS Book 2: Scope and Closures 的第二章(词法范围)中的作弊词法
2021-04-18 03:05:07
感谢您简洁地回答将我带到此页面的问题。结合@MetalGodwin添加的信息,我成功解决了这个问题。现在我只需要解决一个跨域问题,我应该可以无家可归了。
2021-04-25 03:05:07
如果您需要在类内部使用 this,则您无权访问this因为它将指向该函数。
2021-04-25 03:05:07

扩展 Ericks 对 Function 构造函数的回答。

Function 构造函数创建一个匿名函数,在运行时错误时会为调用堆栈中的每个函数(使用 Function 创建)打印匿名函数。这可能会使调试变得更加困难。

通过使用实用函数,您可以动态命名您创建的函数并绕过该困境。此示例还将函数数组中每个函数的所有主体合并为一个,然后将所有内容作为一个命名函数返回。

const _createFn = function(name, functions, strict=false) {

    var cr = `\n`, a = [ 'return function ' + name + '(p) {' ];

    for(var i=0, j=functions.length; i<j; i++) {
        var str = functions[i].toString();
        var s = str.indexOf(cr) + 1;
        a.push(str.substr(s, str.lastIndexOf(cr) - s));
    }
    if(strict == true) {
        a.splice(1, 0, '\"use strict\";' + cr)
    }
    return new Function(a.join(cr) + cr + '}')();
}

关于 Function 构造函数的提示:

由函数表达式定义的函数继承当前作用域。也就是说,函数形成了一个闭包。另一方面,由 Function 构造函数定义的函数不会继承除全局作用域(所有函数都继承)之外的任何作用域。

来源:https : //developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Differences

您能否明确指出:“使调试更加困难”?最终,一个例子会有所帮助。
2021-04-20 03:05:07
你能显示它在实例化后被调用吗?我不习惯调用 _constant 来使用函数。谢谢!
2021-04-26 03:05:07
谢谢@MetalGodwin,感谢您发布了关于函数构造函数的 Mozilla 文档的引文,我从中学到了很多东西,为最终解决使我来到此页面的问题铺平了道路。
2021-04-29 03:05:07
您好,我的意思是,在出现运行时错误时,堆栈跟踪和调试器会为每个创建的函数打印自定义名称而不是“匿名”。我可以更新帖子。
2021-05-15 03:05:07

假设您有一个节点名称数组和一个函数体的并行数组:

var functions = {};
var behaviorsNames = ['behavior1', 'beahvior2'];
var behaviorsBodies = ['this.x++', 'this.y++'];
for (var i = 0; i < behaviorsNames.length; i++){
    functions[behaviorsNames[i]] =  new Function(behaviorsBodies[i]);
}

//run a function
functions.behavior1();

或作为全局变量:

var behaviorsNames = ['behavior1', 'beahvior2'];
var behaviorsBodies = ['this.x++', 'this.y++'];
for (var i = 0; i < behaviors.length; i++){
    window[behaviors[i]] = new Function(behaviorsBodies[i]);
}

以上所有答案都使用了new Function()不推荐方法,因为它会影响您的应用程序性能。您应该完全避免这种方法,并window[classname] = function() { ... };在他的问题中使用@user3018855 提及。

你不知道的 JS 第 2 册:范围和闭包@SimpleFellow 的第二章(词法范围)中阅读作弊词法
2021-04-18 03:05:07
参考“不推荐使用 new Function() 方法”?
2021-04-24 03:05:07