繁体   English   中英

在 JS 中动态创建函数

[英]Creating functions dynamically in JS

我正在为 JS 游戏创建 AI 引擎,它由 Finite State Machines 组成。 我正在从 XML 加载状态数及其变量值。我还想加载行为,并且由于我没有时间创建脚本语言,所以我认为“插入”是个好主意外部文件(XML节点内)的JS代码,按需执行。

像那样的东西

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

对于这样的事情:

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

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

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

编辑 1:

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

window[classname] = function() { ... };

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

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

这样你就可以用参数和body定义一个新函数,并将它赋给变量f。 您可以使用哈希集并存储许多函数:

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

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

扩展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

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

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 在他的问题中提到的那样。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM