Подтвердить что ты не робот

Динамическое создание функций в JS

Я создаю движок AI для JS-игры, и он создан из конечных машин. Я загружаю количество состояний и их значения переменных из XML. Я также хочу загрузить поведение, и поскольку у меня нет времени на создание языка сценариев, я подумал, что было бы неплохо "вставить" JS-код на внешние файлы (внутри узлов XML) и выполнить его на спрос.

Что-то вроде этого

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

Что-то вроде этого:

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

Мой вопрос: теперь, когда у меня загружен код, как его выполнить? Я хотел бы создать функцию с уникальным именем для каждого кода "node", а затем вызвать их из логики игры, но я не знаю, возможно ли это (поскольку вы можете загрузить больше кода JS из HTML, вы также должны быть в состоянии сделать это из JS-кода, нет?). Если нет, есть ли подобное решение? Спасибо заранее!

(PS: чем меньше зависит от внешней библиотеки, тем лучше)

Изменить 1:

Хорошо, теперь я знаю, как создавать функции, содержащие код

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

Ответ 1

Ну, вы можете использовать конструктор Function, как в этом примере:

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

Таким образом вы определяете новую функцию с аргументами и телом и присваиваете ее переменной f. Вы можете использовать hashset и хранить много функций:

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

Загрузка xml зависит от того, запущена ли она на браузере или сервере.

Ответ 2

Чтобы продлить ответ Ericks о конструкторе 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 + '}')();
}

A загорается о конструкторе Function:

Функция, определяемая выражением функции, наследует текущий объем. То есть, функция образует замыкание. С другой стороны, функция, определенная конструктором Function, не наследует никакой области кроме глобальной области (которую наследуют все функции).

источник: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions#Differences

Ответ 3

Предполагая, что у вас есть массив имен узлов и параллельный массив тел функций:

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]);
}