eval和Function可算javascript比较独特的功能,可以将一段代码转成对象或执行。普遍的看法是尽量不要用,因为不安全。其实安全这事,在我看来,主要是要掌握好分寸。盲目相信用户输入,是不安全。但如果你清楚地知道自己在干什么,就不必拘泥于教条。
前两天又用firefox的插件DownthemAll下载东西。这个插件的独特功能就是mask,比如说url是http://abc.com/foo?bar=001&abc=0,http://abc.com/foo?bar=002&abc=0,http://abc.com/foo?bar=003&abc=0......希望批量下载,下载后的文件名为001.jpg, 002.jpg, 003.jpg......这个用一般的下载工具都无法实现,而用Downthemall,可以设置一个mask来实现自动改名。DownthemAll内置了一批mask,大路化的要求能满足,但是比较特殊的url,就需要自己修改代码,增加mask。固然编程不是太难,但毕竟要修改代码,打包,卸载老程序,安装新程序,还是比较麻烦的,尤其对我这样的懒人来说。于是希望增加动态支持自定义mask的功能,就是不必修改代码,而是在使用时,即时(ad hoc)定义mask规则。
首先想到的是写个新的mask,然后在界面上增加一个文本框,让用户输入url的模板。比如http://abc.com/foo?bar=[001]&abc=0,用[]表示变化的部分,也是要提取的部分,[]前后的字符保持不变。然后在mask的处理程序里,根据这个模板,将类似的url,如http://abc.com/foo?bar=002&abc=0中的002提取出来。
这个能应付多数应用。不过觉得还不够灵活,于是就想到,最好允许用户自己写javascript来处理mask,那就真的很灵活了。因为DownthemAll是个浏览器插件,装在用户自己的机器上,别人无法访问(当然了,机器被黑了是另外一回事),输入完全由用户自己控制,所以只要用户自己知道在干什么,我觉得可以不考虑安全问题。
还是写个新的mask,然后在界面上增加一个多行文本框,让用户输入javascript代码,然后在mask的处理程序中,用Function来实现动态解析代码:
export.getAdHocScript = function(url, adhocScript) { let tfunc = new Function('var source= "' + url + '";' + adhocScript; let fileName = tfunc(); return fileName; }
比如url还是http://abc.com/foo/001?bar=0,用户的javascript代码是(作为上面getAdHocScript函数的adhocScript参数输入):
var idxa = source.lastIndexOf("/"); var idxb = source.lastIndexOf("?"); var txt = source.substring(idxa+1, idxb); return txt;
运行后fileName就为001。
当然这里要定义一些规范,比如规定用source这个变量来提供原始的url,相当于用户的javascript的输入参数,用户的javascript最后必须返回转换好的字符串等。
因为貌似浏览器插件不能在运行时动态选择javascript加载起来,所以貌似只能用eval/Function的方法来执行动态的javascript。