eval使用总结:绑到不同的对象上

用JS做个小东西,需要动态执行脚本。于是尝试使用eval函数。

又因为届时会用到大量的函数和对象。所以不想通过命名来规避冲突。

但这样一来突然发现eval就无法满足我的需求了,因为它计算的出来的对象似乎全部绑上了全局的window。

    var code = "var v=123;function test2(){return test() + 2} function test(){return v;}",
ns = {};

function testEval(){
eval(code)
alert("普通eval测试 " + (test?"污染":"没污染window"))
delete test;

eval.call(ns,code)
alert("eval 上下文测试 " + (ns.test?"加入命名空间":"没加入命名空间"))
alert("eval 上下文测试 " + (test?"污染window":"没污染"))
}

 

查看各类资料,无果。更有mozilla。他呀的eval函数的文档居然有2/3是劝你不要使用eval的。晕倒...

自己经过一番苦思,搞出一个变态的解决方案。大体的思路是:

1、制定一个规范,规定需要暴露的接口

2、外面手动的包一层函数,根据规范暴露接口

3、再计算这个对象。

 

Demo如下:

 1    // code是动态的代码(实际的场景是读取目录下的js文件)
2 // 然后规定一个规范,在原先的代码上加上一个数组标记需要暴露的方法或对象
3 var code = "var EXPORT=[test,test2];\n var v=123;function test2(){return test() + 2} function test(){return v;}",
4 head = "new function(){",
5 end = "}",
6 ns = {},
7 magic;
8
9 ns.app = {}
10
11 // 测试函数
12 function nsmng(code){
13 var list = (code.slice(0,code.indexOf("\n"))||"").trim();//读取第一句
14 list = parseExportList(list); // 解析需要暴露的方法或者对象
15 magic=genMagicString(list); // 生成this.xxx=xxx;的代码
16 list = head + code +magic + end; // 拼接代码
17 ns.app= eval(list) // 然后一个匿名函数生成的对象到命名空间
18
19 alert(ns.app.test()) // 测试
20 alert(ns.app.test2())
21
22 // 异常
23 // alert(test)
24 // alert(test2)
25 // alert(v)
26 // alert(EXPORT)
27 }
28
29
30   function parseExportList(list){
31   if(/var\s*EXPORT\s*=\s*\[.*\]\s*\;*$/.test(list)){
32   return list.match(/\[.*\]/)[0].slice(1,-1)
33   }
34   throw "format error"
35   }
36
37   function genMagicString(list){
38   var data = list.split(',').map(function(obj){
39 return "this.%1=%1;".replace(/\%1/g,obj)
40   }).join("\n")
41   return (data)
42
43   }
44
45
46 nsmng(code);


这方面资料比较少,投递这篇,看看有没有人有更好的办法。

 

posted @ 2012-01-03 22:42  倚楼无语F5  阅读(1871)  评论(3编辑  收藏  举报