`
123003473
  • 浏览: 1040914 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

让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?

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

以下是我的实测数据:
function xx(){
    var x= 1 ;
    window .eval ( 'var x=3;' );
    document .writeln (x);
}
xx();


浏览器 IE IE Firefox Chrome Chrome Safari Opera
版本   7.0 8.0 3.0.8 1.0 4.0 4.0.2 9.62
运行结果 3 3 1 3 1 1 1

可见各浏览器及版本对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)          级别:最佳。优点:简洁,干净,可靠,通用。


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

转载:http://www.iteye.com/topic/519098

浅谈Javascript中的with

javascript的作用域是词法作用域(lexical scope or static scope),也就是说作用域链在定义的时候就确定了。也提到eval、with会扰乱作用域链(dynamic scope)。

with
�功能应用。

with会暂时修改作用域链。

<script> function a(){ with (b) { ... } }a(); </script> www.mrw3c.com,专业的网页设计知识库。
函数a在定义的时候,就确定了a的作用域链,我们姑且认为这条链的最顶端是全局对象window。


当函数a被执行的时候,javascript引擎生成了一个call object并将其添加到作用域链尾部上(window对象之后),语句运行到with(b)时,将b添加到作用域链的尾部,所以with之内的变量查找,就会优先从这条链的b上查找---> 然后从a的call object中查找---> 最后查找window。with内的语句执行完之后,作用域链恢复原状(b被移出作用域链)。


以上就是例子代码运行时的微观世界。
with是不被推荐的,因为他操作作用域链(移进、移出,多累),执行效率低下。


有些人可能认为with能节省代码量,比如 编程开发,网站编程与开发,网站后台功能实现。

with(document.forms[0]){ name.value=''; address.value=''; email.value=''; } }
就能少写不少document.forms[0],
其实定义一个局部变量取代with中的b也可以达到同样目的,效率也无损失。 Mr.W3C - 标准网页设计素材库与知识库。


var c=document.forms[0]; c.name.value=''; c.address.value=''; c.email.value=''; Mr.W3C 前期发展,离不开网络文章,您如果看到这些文字请见谅

转载:http://hck.iteye.com/blog/859383
分享到:
评论

相关推荐

    前端开源库-scope-eval

    前端开源库-scope-eval作用域eval,eval传递作用域的字符串

    javascript执行eval函数时利用正则表达式去掉回车符换行符和注释

    在利eval函数执行一段代码时,必须要去掉里面的换行符和回车符,但如果不去掉注释,会出现问题,就是注释后面的所有内容不执行,被当作是注释的内容,所以还要去掉各种注释,这里的解决方案可以把所有注释都去掉

    eval使用方法 matlab

    eval使用方法 matlab

    JavaScript必知必会(五) eval 的使用

    在全局作用域引用eval,改变全局作用域的值,不改变局部作用域的值 var g = eval; //全局引用eval var x = "global";//定义全局变量 (function f() { var x = "local"; g("x+='changed'"); ale

    python基础2day05.txt

    模块级的作用域(全局作用域) 内建模块的作用域 global 语句 声明 nonlocal 语句 lambda 表达式(用来创建匿名函数) lambda 参数列表: 表达式 exec / eval函数 day05 笔记: 函数式编程 函数式编程是指用一...

    揭秘ASP.NET 2.0的Eval方法.doc

    揭秘ASP.NET 2.0的Eval方法,让我们更灵活的使用GridView有兴趣的朋友可以看看。

    详解python中eval函数的作用

    globals — 变量作用域,全局命名空间,如果被提供,则必须是一个字典对象。 locals — 变量作用域,局部命名空间,如果被提供,可以是任何映射对象。 使用示例: 1、字符串转换成列表 a = [[1,2], [3,4], [5,6]

    eval解密脚本 eval解密脚本 eval解密脚本

    eval解密脚本FLASH eval解密脚本 eval解密脚本

    ide-eval-resetter-2.3.5.zip

    ide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d.zipide-eval-resetter-2.3.5-c80a1d...

    测试eval方法所以造成无法通过google closure compiler编译

    eval方法所以造成无法通过google closure compiler编译

    javascript使用eval或者new Function进行语法检查

    虽然new Function( ) 在任何情况下,构造的函数都是在全局作用域下直接工作的,但只作语法检查的话,并不会因为作用域问题而产生意外结果,只要你不直接调用通过它构造的新函数。 在eval&#40; &#41; 接受的参数前面...

    java实现js中eval功能

    使用java来实现js中eval的功能,包括字符串的计算,判断真假等功能

    es6新特性 学习word版2018最新

    (有函数作用域、全局作用域、eval作用域) ES6后,let 和 const 的出现,js 也有了块级作用域的概念,前端的知识是日新月异的~ 变量提升:在ES6以前,var关键字声明变量。无论声明在何处,都会被视为声明在...

    深入认识javascript中得eval函数

    深入认识javascript中得eval函数深入认识javascript中得eval函数深入认识javascript中得eval函数

    Javascript中eval函数的使用方法与示例

    定义和用法 eval&#40;&#41; 函数可计算某个字符串,并执行其中的的 JavaScript 代码。 语法 eval&#40;string&#41; 参数 描述 string 必需。要计算的字符串,其中含有要计算的 JavaScript 表达式或要执行的语句。 ...

    DataBinder.Eval总结

    DataBinder.Eval的基本格式 在绑定数据时经常会用到这个句程序:&lt;%# DataBinder.Eval...今天又学到一种,而且微软也说这种方法的效率要比以上两种高。 ((DataRowView)Container.DataItem)["xxxx"]%&gt; ......

    rank-eval-client-6.2.3-API文档-中英对照版.zip

    赠送jar包:rank-eval-client-6.2.3.jar; 赠送原API文档:rank-eval-client-6.2.3-javadoc.jar; 赠送源代码:rank-eval-client-6.2.3-sources.jar; 赠送Maven依赖信息文件:rank-eval-client-6.2.3.pom; 包含...

    Bind和Eval的区别详解

    eval()方法在运行时使用反射执行后期绑定计算,因此与标准的ASP.NET数据绑定方法bind相比,会导致性能明显下降。它一般用在绑定时需要格式化字符串的情况下。多数情况尽量少用此方法......

    在Web控件模板中使用Eval()方法绑定数据

    在Web控件模板中使用Eval()方法绑定数据

    hcldirgit#studygit#7.Python eval 函数1

    Python eval() 函数描述eval() 函数用来执行一个字符串表达式,并返回表达式的值。globals -- 变量作用域,全局命名空间,如果被提供,则

Global site tag (gtag.js) - Google Analytics