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
分享到:
相关推荐
1. **全局作用域**:当变量或函数定义在所有函数外部时,它们具有全局作用域,可以在整个代码的任何地方被访问。全局变量在整个程序的生命周期内都存在,即使在定义它们的代码块之后。 2. **局部作用域**:在函数...
那么,让我们一起深入研究执行上下文的内部构造,以及它是如何影响我们的代码执行的。 首先,执行上下文可以分为全局执行上下文、函数执行上下文和`eval`执行上下文三种类型。全局执行上下文是代码加载时引擎首先...
4. **变量和命名空间**:Beanshell允许在全局和局部范围内声明和使用变量,同时支持作用域的概念。 5. **类定义和加载**:Beanshell可以动态定义和加载类,这在进行元编程或测试时特别有用。 6. **异常处理**:与...
4. **动态特性**:Ruby支持很多动态特性,如方法定义、变量作用域的改变、运行时类型检查等。源码会展示这些特性的实现原理。 5. **元编程**:Ruby的元编程能力非常强大,允许在运行时修改和创建代码。源码会解释...
虽然在技术层面上它不是一个实际存在的独立对象,但它的所有方法和属性都直接作为全局作用域的一部分可供使用。这意味着我们可以在任何地方调用如`isNaN()`、`isFinite()`、`parseInt()`和`parseFloat()`等方法,...
这通过将Java对象绑定到JavaScript全局作用域实现。例如: ```java engine.put("javaObject", new MyClass()); engine.eval("javaObject.myMethod();"); ``` 5. **转换类型**:Nashorn引擎可以自动在Java和...
解释Tcl中的变量作用域概念,包括全局变量、局部变量的作用域控制,以及如何使用`global`, `upvar`, 和 `unset`命令管理变量。 ### 13. Tcl数据结构 - 列表 介绍Tcl内置的数据结构之一:列表,包括其创建、访问和...
- 全局变量和局部变量部分解释了Scheme语言中变量的作用域和生命周期。 4. **Listen, if-Befehl, do-Schleife, format-Befehl, for-eachSchleife**: - 列表处理是Scheme语言的一个重要特性,文档中讲解了如何...
10. **闭包**: Ruby的块和Proc是闭包,它们能记住定义时的作用域,即使在其他地方调用也能访问那些变量。 通过"rubystudy"项目,你可以练习和了解以上这些概念,逐步掌握Ruby编程。这个项目可能包含示例代码、练习...