2013-11-21 2 views
19

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

Нечто подобное

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

Чтобы что-то вроде этого:

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

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

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

Edit 1:

Итак, теперь я знаю, как создавать функции, чтобы содержать код

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

Я думаю, что вам нужно разработать и, возможно, показать код ... – shennan

+0

http://stackoverflow.com/questions/12964262/create-a-javascript-function-dynamically -from-a-string-name – Triode

+0

'eval', но будьте осторожны, так как это зло. – numbers1311407

ответ

49

Ну, вы могли бы использовать 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 зависит, если он работает в браузере или на сервере.

0

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

var functions = {}; 
var behaviorsNames = ['behavior1', 'beahvior2']; 
var behaviorsBodies = ['this.x++', 'this.y++']; 
for (var i = 0; i < behaviors.length; i++){ 
    functions[behaviors[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]); 
} 
3

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

+0

Можете ли вы объяснить это следующим образом: «* делает отладку сложнее *»? В конечном счете, пример будет полезен. – Stephan

+1

Здравствуйте, я имею в виду, что при ошибке выполнения трассировка стека и отладчик выдает собственное имя вместо «анонимного» для каждой созданной функции. Я могу обновить сообщение. – MetalGodwin

Смежные вопросы