`
hax
  • 浏览: 964704 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

window.eval 及相关方法总结

    博客分类:
  • JS
阅读更多

前面有帖子说到在函数里如何能在全局空间上eval 。 虽然此种需求在绝大多数情况下是不合理的,但是仍有极少数情况可能确实有需要。

JScript有execScript方法可以用来执行脚本。其第一个参数为代码字符串,第二个参数为脚本语言,可以选择jscript或者vbscript。

而在其他脚本引擎中,SpiderMonkey保留了JS最早时候的在对象上的eval方法。也就是在任何对象上,都可以eval,执行时,会把该对象加入scope chain。

例如 {x:1}.eval('x')会返回1,而(o={x:2}).eval('var x = 10')后o.x会等于10。

基本上 o.eval(code); 类似于with (o) { eval(code) }。

唯一值得注意的是var x这样的语句。对于
var o = {x:1};
with(o) {
var x = 2;
}
Safari(JavaScriptCore和KJS引擎)会产生一个全局的x变量。除此之外(JScript、SpiderMonkey、Opera、Rhino等),都会令o.x = 10。注意:前提条件是o上面已经有x属性。

由SpiderMonkey所具有的Object.eval方法,我们可以知道,在Firefox中,window.eval()与直接eval()的效果是不同的。前者的效果接近execScript。

 

【2008年7月6日更新:afcn0同志指出,根据https://bugzilla.mozilla.org/show_bug.cgi?id=382509 ,该方法已经在1.8.1.13(Firefox 2.0.0.13)去除。】

其他引擎不支持Object.eval,但是Opera把window.eval作为一个特例,与Firefox的效果是一样的。除了Safari以外,我们也可以用with(window) {eval(...)}来模拟execScript,但前提是你知道所有在global上声明的var的名字,并预先在window上创建这些变量——多数情况下这不太实际。

SpiderMonkey的eval还可以传第二个参数,eval(code, o)基本等价于o.eval(code),但是两者还是有微妙的差别。如
var a = 'global';
var code = 'alert(a)';
var context = (function () { return function a() {} })();
context.eval('alert(a)');
eval('alert(a)', context);
这两次返回的值是不同的。在eval(code, o)的时候,会继续从o.__parent__(即[[scope]])开始寻找。而函数表达式的名字,或者函数外部的with语句,都会给其[[scope]]增加一层对象。

关于new Function(code),实际上PIES就是使用的这个方法来生成代码而不是像其他一些框架那样使用eval。另外我还用它来做对模板的“编译”。使用Function比eval要好很多。因为它总是在一个新的execution context上,从而避免了许多eval可能出现的bug(早期版本的浏览器经常在某些特殊eval时崩溃)。所以如果需要生成代码,应优先使用new Function。

但是new Function对于需要执行var x=1,把x放到global的需求,是不合适的。虽然这种需求非常罕见(以至于多数情况下这种需求是错误的需求),但因为本文恰恰是说这个问题,因此就略过。

事实上,对于SpiderMonkey和Rhino来说,还有另一个方法,也是推荐的方法,那就是使用Script方法。Script(code)的结果是一个函数,可以直接调用。例如Script('var a = 1')(),无论在哪里执行,都会在global上产生a变量。实际上Script结果的调用就是对Script.prototype.exec的调用。Script.exec,基本上是execScript的真正对应。注意,Rhino上必须直接调用而不能用Script(code).exec()调用。SpiderMonkey上Script.exec可以带有参数,如果带有参数obj,效果就跟eval(code, obj)接近。

好,最后总结一下:

JScript上使用execScript(code)
SpiderMonkey和Rhino上可使用Script(code)()
Opera下使用window.eval(code)

唯一的问题是Safari。实际上window.eval已经被作为一个bug被提交并且fixed了(参考http://trac.webkit.org/projects/webkit/changeset/25535 ),我们希望下一个版本的Safari应该就可以与Opera一样,使用window.eval了。

分享到:
评论
4 楼 robbin 2007-11-02  
编辑器的问题修改起来在2.0的代码上面修改起来异常麻烦,但是3.0完全重写的代码已经解决了bug和浏览器兼容性问题。

BTW:我用的也是Opera
3 楼 louisling 2007-11-02  
对啊, 希望 Robbin 能够看到就好!
2 楼 hax 2007-09-24  
正文更新完毕。
BTW,javaeye目前的编辑器在Opera下会使用WYSIWYG的编辑器,但是又不能正确的显示出来,算是个较严重的bug了。
1 楼 afcn0 2007-09-24  
不用那么麻烦,eval的context是保存的外面function的context,只要外面是window级别的就可以了
>>> function a(){var b=123;c=function(a){return eval(a)}}
>>> a()
>>> c("b")
123
>>> function a(){var b=123;c=new Function("a","return eval(a)")}
>>> a()
>>> c
anonymous(a)
>>> c("b")
b is not defined
[Break on this error] undefined
javascript: with ... (line 1)
>>> var b=234
>>> c("b")
234
先头的c是a里面的function,所以eval的scope是先c再a再window,第二次是用new Function所以直接把c弄到window下面,所以c的eval是先c再window,和a没关系了,execScript可能和这种new Function一样吧,不会产生scope链吧,并且好似execScript没有返回值
var b=234;
function a(){var b=123;c=function(a){return execScript(a)}}
a();
alert(c("alert(b);b"))

相关推荐

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

    2. 使用`window.eval()`:在某些情况下,如果必须使用`eval()`,可以将它限制在全局作用域,通过`window.eval()`调用,这样Closure Compiler可以识别这是一个全局操作。 3. 使用`@nocache`注释:在`eval()`前添加`/...

    深入认识javascript中得eval函数

    这里需要注意的是,虽然`X2.Eval`内部也使用了`eval`,但由于它是通过`window.eval`调用的,所以它仍然会在当前作用域内执行。 #### 六、总结 尽管`eval`函数提供了强大的功能,但鉴于其可能带来的安全性和性能...

    javascript中eval和with用法实例总结.docx

    ### JavaScript中的`eval`与`with`用法详解 #### 一、`eval`函数 ##### 1. 定义 `eval`是JavaScript中一个非常强大的内置函数,它可以将字符串解析并执行为JavaScript代码。这使得开发者能够在运行时动态地创建和...

    ASP javascript

    根据给定的信息,我们可以归纳总结出以下几个重要的知识...以上是基于提供的部分代码内容总结的ASP中JavaScript的使用方法及相关知识点,这些方法可以帮助开发者更好地在ASP页面中嵌入和使用JavaScript来增强用户体验。

    AS语言获取url参数的说明

    这里的代码利用了`ExternalInterface.call`方法调用了JavaScript中的`eval`函数来执行`window.location.href`,从而获取到了完整的URL。 ##### 2. 获取协议 协议可以通过`window.location.protocol`来获取。例如:...

    javascript eval函数深入认识

    JavaScript 的 `eval` 函数是一个强大且复杂的工具,主要用于将字符串转化为可执行的 ...对于在函数内部执行全局代码,可以利用浏览器的特定方法,如 `execScript` 和 `window.eval`,但也要注意浏览器兼容性问题。

    1_d_eval_js_1.txt

    根据提供的文件信息,我们可以分析出该文件主要涉及的是HTML与JavaScript相关的知识点,特别是与`<iframe>`元素以及JavaScript中的`eval()`函数的应用有关。接下来,我们将深入探讨这些知识点。 ### ...

    Firefox和IE兼容性问题及解决方法总结

    IE中,`window.event`对象用于访问当前事件的相关信息,但在Firefox中,事件信息是通过事件处理函数的参数传递的。要兼容两者,可以在事件处理函数中检查`event`参数,如果没有,则从`window`对象中获取: ```...

    实用的代码

    根据提供的信息,我们可以总结出以下ASP.NET相关的知识点: ### ASP.NET 实用代码示例与解析 #### 1. 显示提示并跳转页面 ```csharp // 显示提示信息并进行页面跳转 CODE: Response.Write("<script>window.alert...

    JavaScript中eval()函数用法详解

    为了兼容不同浏览器,可能需要使用window.eval()方法,或者在IE中使用window.execScript()。例如: ```javascript if (window.execScript) { window.execScript("var x = 1;"); } else { window.eval("var x = 1;...

    ASP.NET常用语句

    Response.Write("<script>window.alert('该会员没有提交申请,请重新提交!')</script>"); Response.Write("<script>window.location ='http://www.51aspx.com/bizpulic/upmeb.aspx'</script>"); 该语句用于弹出一...

    \ASP.NET实现自适应图片大小的弹出窗口(窗口可任意编辑).doc

    此函数通过`window.open`方法打开一个新的浏览器窗口,其中`pic_all.aspx`页面将根据传入的ID参数加载具体的图片信息。 3. **自适应窗口大小** 为了使`pic_all.aspx`页面能够根据图片大小自动调整窗口尺寸,需要...

    FF和IE的兼容性问题总结

    3. **自定义属性**:IE允许通过常规属性方法或`getAttribute()`获取自定义属性,而FF仅支持`getAttribute()`。为了兼容,应始终使用`getAttribute()`。 4. **ID查找**:IE下可以用`eval("idName")`或`...

    将自己开发的JSP设置为internet首页的代码!

    这段代码仅在IE浏览器下有效,利用`window.external.AddFavorite`方法可以将指定的网址添加到用户的收藏夹中。 ##### 方法二:兼容多种浏览器的添加收藏夹功能 ```javascript function addFavorite(url, title) { ...

    如何在Silverlight控件中与Html元素交互

    在Silverlight中,我们可以使用`HtmlPage.Window.Eval()`方法执行JavaScript代码。例如,如果你想改变一个HTML元素的文本,可以在Silverlight中编写如下代码: ```csharp HtmlPage.Window.Eval("document....

    一些.NET经典代码

    ASP.NET提供了强大的数据绑定功能,可以直接在数据模板中使用`DataBinder.Eval`方法来访问数据项的属性,并使用`DateTime`类的`ToShortDateString`方法来格式化日期。 ```csharp <%# System.DateTime.Parse...

    html应用小程序欢迎下载

    - `eval("window.j=0")`: 使用 `eval()` 函数来动态执行字符串作为 JavaScript 代码。虽然这种方式可以实现动态变量声明,但在实际开发中不推荐使用,因为它可能会导致安全问题和代码可读性差的问题。 - 其他类似的...

    javascript在firefox与ie下的兼容性总结

    - 解决方法:使用`document.getElementById(idName)`代替`eval(idName)`。 6. **变量名与HTML对象id相同的问题** - 问题描述:在Firefox中,可以使用与HTML对象id相同的变量名,但IE不允许。 - 解决方法:始终在...

    IE 与FireFox 区别概要总结

    - 用`eval("idName")`在IE中获取ID为"idName"的对象,但Firefox不支持。推荐使用`document.getElementById("idName")`。 8. 变量名与HTML对象ID相同: - 在Firefox中,变量名不会覆盖HTML对象ID,但在IE中可能会...

Global site tag (gtag.js) - Google Analytics