2

特定のデータに対して実行するアクションのリストであるタスクを定義する XML ドキュメントがあります。この「タスク リスト」を、後で呼び出すことができる Javascript メソッドに変換する必要があります。このメソッドは、適切なデータを使用して一連の事前定義されたメソッドを呼び出します。どうすればこれを達成できますか?

重要な説明:
XML の解析については心配していません。重要なデータを定義済みのアクション メソッドにバインドするなど、タスク メソッドを実際に構築する方法に興味があります。それは私が苦労している部分です。

編集:例を修正して、もう少し面白くし、できればもう少し明確にしました。

XML:

<task id="enter-castle">
    <if holding="castle-key">
        <print message="You unlock the castle door and enter." />
        <destroy item="castle-key" />
        <goto location="castle" />

        <else>
            <print message="The castle door is locked." />
        </else>
    </if>
</task>

Javascript:

Game = {

    print: function(message) {
        // display message
    },

    destroy: function(item) {
        // destroy the object
    },

    goto: function(location) {
        // change player location
    },

    ifHolding: function(item) {
        // return true if player has item
    }
};

parseTask(taskNode) {

    var taskId = taskNode.getAttribute('id');

    // What goes here??

    Game.tasks[taskId] = /* ??? */;
}

ノードを呼び出すparseTask()と、呼び出されたときに実際に次のことを行う関数が作成されます。<task id="enter-castle">

Game.tasks.enterCastle = function() {
    if (Game.ifHolding('castle-key')) {
        Game.print("You unlock the castle door and enter.");
        Game.destroy('castle-key');
        Game.goto('castle');
    } else {
        Game.print("The castle door is locked.");
    }
}
4

3 に答える 3

3

あなたが望むのはクロージャーです。

function createMethod(arguments) {
    var task = doSomethingWithYour(arguments);
    return function(xmlData) { // <- this is the fundamental part
        // do the task with your data
        // the "task" vars are still available
        // even if the returned function is executed in a different context
    }
}

これにより、タスクごとに独自のメソッドを作成できます。Function コンストラクターまたは eval を使用しないでください。

于 2012-03-03T18:46:10.003 に答える
2

これは、 JavaScript のeval()機能があなたの生活をずっと楽にしてくれる状況です。目的の文字列に一致する JavaScript ソース文字列を簡単に作成し、それを評価して、Game オブジェクトの目的のプロパティに関数を割り当てることができます。

もちろん、「eval」の使用には欠点がありますが、Web で使用しない理由は無数にあるため、この回答では説明しません。ただし、単純な JS ソース文字列の構築と評価は、パフォーマンスとセキュリティの潜在的な欠点にもかかわらず、短期的にはクロージャー ベースのソリューションよりもはるかに簡単になります。さらに、「eval」ベースのソリューションは、評価される前にソース文字列を簡単に検査できるため、テストが容易になります。

だから、次のようなことを試してください:

function buildTaskFunction(taskXml) {
  var source='', depth=0, node /*a visitor to each DOM node*/;
  // foreach (node in traverseInOrder(taskXml)) {
    switch (node.nodeName) {
      case 'TASK':
        source += 'Game.tasks.' + makeFunctionName(node.id) + '= function(){';
        depth++;
        break;
      case 'IF':
        source += 'if(' + getConditionalAttribute(node) + '){'
        depth++;
        break;
      case 'ELSE':
        source += '}else{';
        break;
      case 'DESTROY':
        source += 'Game.destroy("' + node.getAttribute('item') + '");'
        break;
      case 'PRINT':
        source += 'Game.print("' + node.getAttribute('message') + '");'
        break;
      // case etc...
      default: throw new Error('unhandled node type "' + node.nodeName + '"');
    }
  // end "foreach node".
  while (depth-- > 0) { // You'll need to account for nested "if"s somehow...
    source += '}';
  }
  eval(source);
}

繰り返しますが、「eval」の使用には多くの潜在的な問題 (決定的な問題ではない) があるため、それらについて読んで、ソリューションのコンテキストで理解するようにしてください。自分のプログラムで欠点が利点に見合うかどうかを判断するときは、自分で判断してください。ツールが危険であるからといって、それを使用すべきではないということにはなりません。

于 2012-03-03T19:05:29.343 に答える
0

dojoの使用例:

dojo.require("dojox.xml.parser");

dojo.ready(function(){
  // Parse text and generate an XML DOM
  var xml = "<tnode><node>Some Text</node><node>Some Other Text</node></tnode>";
  var dom = dojox.xml.parser.parse(xml);

  var docNode = dom.documentElement();
  // ...
}

関数の残りの部分は重要ですが、主にを使用した属性ルックアップとを使用['<attribute-name>']した子ノードの反復で構成されます。dojo.forEach(<node>.childNodes, function(childNode) { /* do stuff */ });

于 2012-03-01T20:57:03.557 に答える