Javascript:如何从字符串数据动态构建方法
Javascript: How to build a method dynamically from string data?
我有一个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] = /* ??? */;
}
当我在<task id="enter-castle">
节点上调用parseTask()
时,这应该创建一个函数,该函数在调用时执行以下操作,实际上是:
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.");
}
}
您想要的是闭包。
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。
在这种情况下,JavaScript的eval()
函数将使您的生活更加轻松。你可以很容易地构建一个与你想要的匹配的JavaScript源字符串,并对其进行评估,将函数分配给你的游戏对象的期望属性。
当然,使用"eval"也有缺点,我不会在这个答案中探究,因为你可以找到无数的理由来解释为什么不在网络上使用它。然而,在短期内,构建和评估一个简单的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"有许多潜在的问题(不是决定性的问题),所以请阅读并尝试在解决方案的上下文中理解它们。在决定自己的程序中的缺点是否值得好处时,请使用自己的判断——仅仅因为一个工具可能很危险并不意味着你不应该使用它。
使用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 */ });
的子节点迭代组成。
- 下载使用POST数据动态生成的文件
- 使用enyo.js将数据动态插入表中
- (Laravel)使用数据库中的数据动态打开模态
- 如何根据数据动态创建引导下拉列表
- 将json数据动态加载到D3节点中
- 如何在 React 中将 html 表单元格数据动态插入到具有动态标题的表中
- 使用数据库返回的数据动态填充下拉列表
- 从 JSON 数据动态创建 Jquery 移动导航栏
- 将数据动态发送到服务器
- 如何通过角度 ui-grid 中来自$scope的数据动态设置指令
- 如何在 ASP.NET 中将数据动态追加到 JQuery 控件变量
- 用于流程图的 JavaScript 绘图库,并将数据动态附加到视图
- 使用Angular ng-repeat将数据动态加载到materializecss滑块中不起作用
- 在 Laravel 5.1 和 Vue JS 中保存多个数据动态表单
- 当没有提供json数据的结构/字段名称时,将json数据动态显示为表
- 如何使用entityframwork和sql数据动态显示jqgrid数据
- Javascript:如何从字符串数据动态构建方法
- Javascript:将数据动态添加到数组中
- Ember数据动态模型未加载到存储中
- 使用JSON URL数据动态填充HTML表