我是否应该使用eval()
开始一场战争,我试图就如何在以下情况中避免(如果可能)使用eval()
进行建设性讨论?
我正在将远程html模板加载到SPA中,以保存我正在加载json的调用,如下所示:
{
"template":"",
"contentScript":"",
"viewModel":""
}
如果模板是html,则contentScript是组合脚本文件,viewModel是单个脚本文件。
ContentScript
当收到json请求时(来自server或localdb)我创建了一个匿名函数(所以所有变量都本地作用于此模板脚本),用于看起来像这样的内容:
(function(event, view)
{
// js content here
});
其中事件对象是contentScript和viewmodel使用pub / sub模式进行通信的共享对象,而view对象是作为模板的DOM元素。
我能看到让这种模式运作的唯一方法是使用以下代码:
var script = 'function(event, view) {' + json.contentScript + '});';
views[name].script = eval(script);
其中views [name]是SPA中所有模板的集合,因此我可以获取它们并使用名称轻松重新绑定它们。
每次渲染视图时我都可以简单地调用(执行脚本):
views[name].script.apply(window, [ views[name].eventObj, views[name].view ]);
视图模型
视图模型略有不同,因为我需要该对象的属性才能显示绑定,因此它不能是匿名函数。为了实现所需的结果,我将viewModel对象创建为对象文字,如:
var viewmodel =
{
init: function(event, view)
{
this.event = event;
this.view = view;
},
... other stuff
}
当收到viewModel json时,我在它上面运行一个正则表达式,以确保init签名符合预期,然后eval()
就像:
eval(json.viewModel);
views[name].model = observable(viewmodel); // viewmodel var is available from eval'ing the contentScript
views[name].model.init(views[name].eventObj, views[name].view);
新功能
我也尝试使用Function('script as string')
,这也是不赞成的。但是这并不支持这两种情况,因为它在我的匿名函数周围创建了一个匿名函数,需要额外的一步来检查参数以将变量传递给我的匿名函数。更重要的是,它还隐藏了对象文字的属性,防止数据绑定工作。
结论
我看不出我在这里做的任何问题,但我很好奇如何使用其他方法实现这一点。我花了很多时间尝试不同的想法,没有一个允许两个场景有效地工作。
答案 0 :(得分:1)
如何在这种情况下避免使用eval()?
我看不出我在这里做的任何问题,但我很好奇如何使用其他方法实现这一点。我花了很多时间尝试不同的想法,没有一个允许两个场景有效地工作。
我相信这个问题值得回答。
由于您想在本地范围内评估您的Javascript代码字符串,因此我不相信在您的情况下可以避免使用eval
。一句警告。
找到一些有趣的阅读材料eval()是一个危险的函数,它使用调用者的特权执行它传递的代码。如果您使用可能受恶意方影响的字符串运行eval(),您最终可能会使用您的网页/扩展程序的权限在用户的计算机上运行恶意代码。更重要的是,第三方代码可以看到调用eval()的范围,这可能导致类似函数不受影响的可能攻击。