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();
|
浏览器
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)
级别:最佳。优点:简洁,干净,可靠,通用。
N整一个表格比较清楚:
让eval()全局作用域执行的方法
级别
缺点
优点
(1)window
.execScript
+ window
.
eval
|
弱 |
不简洁,不可靠,不通用 |
- |
(2)document
.
createElement
("script"
) |
凑合 |
不简洁,不干净 |
可靠,通用 |
(3)with
(
window
)eval
(strScript)
|
最佳 |
- |
简洁,干净,可靠,通用 |
事情到这里,才可以去休息一下了。
分享到:
相关推荐
JavaScript 执行环境和作用域的深层次理解 在 JavaScript 中,执行环境和作用域是两个非常重要和基本的概念,理解了这两个概念对于 JavaScript 中很多脚本的运行结果就能明白其中的道理了。执行环境是一个概念,一...
另外,所有`window`对象的属性和方法也具有全局作用域。 局部作用域,或称函数作用域,只在函数内部有效。这意味着在函数外部无法访问在函数内部定义的变量。例如,如果在函数`hello()`中声明了一个变量`a`,则只有...
`scope-eval`通过创建一个新的局部作用域,使得`eval`在执行时只能访问这个新作用域内的变量,从而避免了对全局作用域的不必要干扰。 `scope-eval`的工作方式如下:当调用`scope-eval`并传入一个字符串和一个对象...
在查找变量时,引擎会从当前作用域开始,如果找不到,就向上级作用域查找,直到找到全局作用域。例如,如果在函数内部使用未声明的变量,会抛出`ReferenceError`;而在函数内部定义变量后,该变量仅在该函数作用域内...
当在函数内部使用`eval`时,它将按照该函数的作用域执行代码。这意味着`eval`内部可以直接访问该函数的局部变量和其他作用域内的变量。这也意味着`eval`可以修改这些变量的值,这可能会导致意料之外的结果。 ##### ...
在这个例子中,`eval()`函数在全局作用域被调用,定义了全局变量`y`,并且可以在全局作用域中被访问。 #### 三、eval函数的执行上下文 `eval()`函数的执行上下文与调用它的上下文环境相同。这意味着: - **局部...
### JavaScript执行环境及作用域详解 #### 执行环境概述 执行环境定义了变量或函数能够访问的数据以及其他相关信息,它决定了这些变量和函数的行为方式。在JavaScript中,执行环境的概念至关重要,因为它不仅涉及...
2. 使用`window.eval()`:在某些情况下,如果必须使用`eval()`,可以将它限制在全局作用域,通过`window.eval()`调用,这样Closure Compiler可以识别这是一个全局操作。 3. 使用`@nocache`注释:在`eval()`前添加`/...
JavaScript执行环境及作用域详解: JavaScript的执行环境和作用域是理解这门语言核心概念的关键部分,它影响着变量和函数的作用范围以及生命周期。执行环境定义了变量或者函数有权访问的其他数据,而作用域则决定了...
值得注意的是,`eval`在不同作用域下有不同的行为:如果在全局作用域中,它可以访问和修改全局变量;而在函数作用域中,它通常只能访问局部变量(除非使用`var`声明)。 四、安全问题 `eval()`的主要危险在于它...
4. **内置属性和方法**:全局对象拥有内置的方法,如`eval()`用于执行字符串形式的JavaScript代码,`setTimeout()`和`clearTimeout()`用于定时器操作,以及`parseInt()`和`parseFloat()`用于转换数字等。 现在,...
在Python中,主要有四种作用域:局部作用域(定义在函数内)、全局作用域(定义在模块级别)、嵌套作用域(定义在闭包内)和内置作用域(Python内置的变量)。`global`关键字用于在函数内引用全局变量,而`nonlocal`...
3. **执行上下文(Execution Context)**:这部分代码负责提供执行环境,如变量存储、作用域管理等。 4. **安全性控制(Security Control)**:由于执行用户提供的代码存在潜在的安全风险,自定义的`eval`函数应该...
JavaScript中的`eval()`函数是一个非常强大的工具,它能够将字符串作为JavaScript代码来执行。然而,直接使用`eval()`可能存在安全风险,比如代码注入攻击。在某些特定场景下,我们需要对输入的字符串进行预处理,...
作用域和作用域链是深入理解JavaScript工作原理的关键。通过理解作用域和作用域链,程序员可以更准确地预测代码的执行行为,避免一些常见的作用域相关错误,比如闭包问题、变量遮蔽问题等。在实际开发中,合理利用...
1. **`new Function()`**:虽然也存在安全问题,但相比`eval()`,`new Function()`限制了作用域,可以用来替代简单的脚本执行: ```javascript let func = new Function('param1', 'param2', 'return param1 + param...
例如,当在全局作用域中调用`eval`声明了一个变量,这个变量在全局范围内是可见的;而在函数内部调用`eval`,变量则只限于该函数的作用域。 在SpiderMonkey引擎(Firefox和Thunderbird的一部分,自1.7版本起)中,...
这些文件可能探讨了不同场景下`eval()`的使用,例如在全局作用域和局部作用域中,或者与闭包结合时的情况。 总的来说,理解如何在JavaScript中安全、有效地使用`eval()`和`delete`操作符是一项重要的技能。需要注意...
另外,如果你需要在特定的上下文中执行代码(例如,访问类成员或变量),那么你可能需要使用`ScriptRuntime`和`ScriptEngine`,并传递适当的全局作用域和上下文对象。 总的来说,虽然C#没有直接提供`eval()`这样的...
因此,更安全的做法是手动创建作用域链和执行环境,比如使用`Proxy`来控制对特定对象的访问。 接下来,我们讨论`eval()`的另一个常见用途——解析和执行JSON数据。由于JSON是JavaScript的一个子集,我们可以使用`...