首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 网站开发 > Web前端 >

让eval()在大局作用域中执行的方法

2012-11-06 
让eval()在全局作用域中执行的方法?? ?eval(str) 用来传入一个字符串动态执行一段脚本,这个方法非常有用。

让eval()在全局作用域中执行的方法

?? ?eval(str) 用来传入一个字符串动态执行一段脚本,这个方法非常有用。当直接用eval()时,作用域为当前作用域,有时候我们需要让它在全局作用域范围内执行,比如 ajax返回的脚本字符串,然而浏览器对eval的差异可能使事情刚开始并不是那么顺利,本文通过在7种浏览器(IE, Firefox, Chrome, Safari, Opera)环境中测试,并提出三种解决方案,使这个问题比较完美的解决。

?

看这一段javascript代码:

function?xx(){?
? ??var?x=?1?;?
? ??window?.eval(?'var x=3;'?);?
? ??document?.writeln(x);?
}

xx();

在你自己测试和看我接下来的分析之前,先想想,你认为输出结果会是什么呢?是1还是3?

根据本文的标题,可知肯定是在不同浏览器下有不同表现的。

以下是我的实测数据:

JS代码function?xx(){?
? ??var?x=?1?;?
? ??window?.eval?(?'var x=3;'?);?
? ??document?.writeln?(x);?
}?
xx();浏览器IEIEFirefoxChromeChromeSafariOpera版本7.08.03.0.81.04.04.0.29.62运行结果3313111

?

可见各浏览器及版本对window.eval()的作用域处理是有差异的。

IE中,window.eval()和eval()一样只在当前作用域生效。

Firefox,Safari,Opera中,直接调用eval()为当前作用域,window.eval()调用为全局作用域。

尤其值得注意的是,Google Chrome 的不同版本之间对于eval的处理也有差异。

?

?

如果需要在全局作用域eval()的效果,且通用于所有浏览器,那就得好好变通一下了。

?

方法之一:

使用IE专有的window?.execScript?。

如果你碰到这个问题不知所措,并上网搜索,这个方法大概是最先也几乎唯一能搜索到的方法。

window?.execScript?(sExpression?,?sLanguage?)。

比如上面那一段代码中eval一句如果换成window?.execScript(?'var x=3;'?);?IE中的运行结果就是1了。

非IE内核的浏览器并不支持window?.execScript?。

IE之所以有这个window?.execScript?,还和IE能够执行其他语言的脚本有关,通过给不同的sLanguage?参数,IE这个方法除能够执行javascript之外,还可以执行vbscript或是其他任何安装过相应解释引擎的脚本如perl,python等。

?

当需要在局部环境中执行的时候,我们就直接用eval()。

当需要在全局环境中执行的时候,我们可以封装一个通用的函数,就像下面这样:

?

//在全局环境中执行

function??evalGlobal(strScript){
??? if(?window?.execScript)?window?.execScript(?strScript?);

? ??else?window?.?eval?(?strScript?);?
}

就是将IE和非IE区别开来对待。

看起来,问题似乎圆满解决了。但是显然是有问题的,比如上表中的Chrome 1.0也和IE的eval()规则一致,况且还不知道其他浏览器其他版本是否有差异呢,因此,这种方法并不很可靠。

?

但是如果你有一点完美主义者的倾向,那么事情还不能到此为止,肯定是有更好更简洁的方法的嘛。

不知道阅读此文的你是否有想到呢?

是否和我的想法一致呢?

?

方法之二:

新建一个<script>元素装载脚本。

这种方法常用来解决innerHTML中的脚本不能运行的问题。但用来解决eval()的作用域问题,恐怕就比较罕见了。

//在全局环境中执行

function??evalGlobal(strScript){

??? ????var?a?=?document?.createElement?("script"?);
??? ????a.type=?"text/javascript"?;
??? ????a.text=?strScript?;
??? ????document?.getElementsByTagName?("head"?)[0?].appendChild?(a)?;
}

虽然这个方法有点变态,需要新增一个<script>元素,但优点是各种浏览器及版本通用,比方法一要好一些了。。

?

?

但是如果你有再多一点完美主义者的倾向,那么事情还不能到此为止,毕竟添加了一个HTML元素嘛,影响了页面原本的DOM结构。

那么是不是有更好更简洁的方法的呢?答案是肯定的。经过我的研究,找到了同时具备简洁和可靠的方法三。

不知道阅读此文的你是否有想到呢?

是否和我的想法一致呢?

?

方法之三:

还是eval。回归原生态。

我们别忘了javascript里面有一个改变上下文环境的关键字,强大的with?.

原来事情可以更简单更有效!

//在全局环境中执行

function??evalGlobal(strScript){

??? ????with?(?window?)eval?(strScript)?;
}

看看,都这么简单了,我们完全可以不用封装为函数了,直接在代码中用。

?

文章最开始的代码我们就可以这样来了:

function?xx(){?
? ??eval?(?'var x=1;'?);???//局部变量?
? ??with?(?window?){?eval?(?'var x=3;'?);}???//全局变量?
????//也可以用封装的 evalGlobal( 'var x=3' );?
? ??document?.writeln?(x);???//1? 局部变量?
? ??document?.writeln?(?window?.x);???//3? 全局变量?
}?
xx();

?

特别:

有时候,我们eval()要求既不是在全局执行,也不是在当前作用域执行,而是在父对象或子对象中执行,这时,用?with?(?objContext?)eval?(strScript)就更加是不可替代的选择了。


?

总结:

让eval()全局作用域执行的方法主要有:

(1)window?.execScript?+?window?.?eval??? 级别:弱。 缺点:不简洁,不可靠,不通用。

(2)document?.?createElement?("script"?)??? 级别:凑合。缺点:不简洁,不干净。优点:可靠,通用。

(3)with?(?objContext?)eval?(strScript)????????? 级别:最佳。优点:简洁,干净,可靠,通用。

?

N整一个表格比较清楚:

让eval()全局作用域执行的方法级别缺点优点?(1)window?.execScript?+?window?.?eval?弱?不简洁,不可靠,不通用?-?(2)document?.?createElement?("script"?)?凑合?不简洁,不干净?可靠,通用?(3)with?(?window?)eval?(strScript)?最佳?-?简洁,干净,可靠,通用

?

?

热点排行