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

运行时的代码串执行:eval与Function

阅读更多

两个很少用到的特性,谨慎使用!


看代码先:

 

var i=2;
function g2(){
	alert(i);
}

function do2() {
    var i=1;
    function	go2(){
    	alert(i);
    }
    eval("alert('eval : '+i);");
    if(window.execScript)
    	window.execScript("alert('window.execScript : '+i);");
    else if(window.eval)
    window.eval("alert('window.eval : '+i);");
    new Function("alert('new Function : '+i);")();
    setTimeout("alert('setTimeout code String : '+i);",1);
    setTimeout(g2,1);
    setTimeout("g2();",1);
    setTimeout(go2,1);
    setTimeout("alert('error is coming : ');go2();",1);
}
do2();

 


结果大家可以先想想  .................

运行时代码执行

使用 eval 会造成 yui compressor 压缩代码时由于不能静态判定 eval 中的代码串变量引用而造成eval语句所在的整条作用域链中的变量都不能被简短命名,

 

function compressHarm(){
   var lllllllllllllllllllllllllllllllllllllllllllllll='l',a='lllllllllllllllllllllllllllllllllllllllllllllll';
   //没法实行命名简写 lllllllllllllllllllllllllllllllllllllllll
   eval('alert('+a+')');
}

 

压缩后:

 

function compressHarm(){var lllllllllllllllllllllllllllllllllllllllllllllll="l",a="lllllllllllllllllllllllllllllllllllllllllllllll";
eval("alert("+a+")")}compressHarm();
 

 

所以推荐使用全局执行函数,比如全局eval,new Function或异步添加脚本执行。

 

PS:google closure compiler 很厉害,好像会动态执行脚本,会先执行后再优化压缩(甚至会帮你删除他认为不必要代码),比如这里的出错压缩:

 

function compressHarm(){eval("alert(lllllllllllllllllllllllllllllllllllllllllllllll)")}compressHarm();


但是当你 eval 中没有变量引用时就不可思议了:


压缩前:

 

function compressHarm(){
   var lllllllllllllllllllllllllllllllllllllllllllllll='l',a='lllllllllllllllllllllllllllllllllllllllllllllll';
   //yui compressor 没法实行命名简写 lllllllllllllllllllllllllllllllllllllllll,没法动态分析
   eval('alert(1)');
}

compressHarm();
 

压缩后:

 

function compressHarm(){eval("alert(1)")}compressHarm();

 

updated 2010-11-09:

 

更多详见:应用 closure compiler 高级模式

 

 

 

1.不涉及闭包的全局eval

 

上述例子使用 window.eval (firefox) 与 window.execScript (ie) 都不是标准规定,且存在浏览器间的不一致性。若要遵从标准,适当的做法为 2,3。


2.使用 new Function

 

由于 new Function 生成函数时,会把全局环境作为生成函数的 [[Scope]] 属性,则不存在作用链引用问题。


1,2 相对于 3 为同步调用,并可将调用处的变量作为参数传递,来平衡 eval 的变量引用以及作用域链引用问题,而对于 2 更因为 new Function 可以设定函数参数,则可传对象引用,对于 1,由于是执行代码串,则只能将变量序列化后传过去。

 

 

//避免 eval 的作用域链引用问题,主要便于压缩
function test(){
 var a={},b=1;
  //只能变量序列化
  if(window.execScript) {
       window.execScript("alert("+b+")");
   }else{
        window.eval("alert("+b+")")
   }
   
   //可传任意 
   (new Function("par,obj","alert(par);alert(obj);"))(b,a);

}

 

setTimeout/setInterval :如上例所示参数为字符串时,实际上就是 new Function 不设置函数参数的异步情况。

 

3. 在head中动态 异步添加内联脚本 ( body 中需要插到第一个子结点前,否则IE6 在 DOM ready 前会有问题:abort error)

 

<head>
<script>alert("inline script");</script>
</head>

而关于脚本的具体动态添加则又有区别:

 

标准浏览器用 script.appendChild( document.createTextNode( data ) );即可

而 ie 则需用 script.text = data;(标准浏览器也可以)


于是得到下列代码:(From Jquery)

 

// Evalulates a script in a global context
	globalEval: function( data ) {
		if ( data && rnotwhite.test(data) ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";

			if ( jQuery.support.scriptEval ) {
				script.appendChild( document.createTextNode( data ) );
			} else {
				script.text = data;
			}

			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},
 

注意 3 的方式不能同步调用获得返回结果。

 

 

 

 

PS:附录 ecmascript262-5th ,摘录

 


10.1 Types of Executable Code
There are three types of ECMAScript executable code:
•  Global code is source text that is treated as an ECMAScript  Program.
•  Eval code is the source text supplied to the built-in eval function.
•  Function code is source text that is parsed as part of a  FunctionBody.


10.4.1 Entering Global Code
The following steps are performed when control enters the execution context for global code:
1.  Initialize the execution context using the global code as described in 10.4.1.1.
2.  Perform Declaration Binding Instantiation as described in 10.5 using the global code.


10.4.1.1 Initial Global Execution Context
The following steps are performed to initialize a global execution context for ECMAScript code C:
1.  Set the VariableEnvironment to the Global Environment.
2.  Set the LexicalEnvironment to the Global Environment.
3.  Set the ThisBinding to the global object.


10.4.2 Entering Eval Code
The following steps are performed when control enters the execution context for eval code:
1.  If there is no calling context or if the eval code is not being evaluated by a direct call (15.1.2.1.1) to the eval
function then,
a.  Initialize the execution context as if it was a global execution context using the eval code as C as
described in 10.4.1.1.
2.  Else,
a.  Set the ThisBinding to the same value as the ThisBinding of the calling execution context.
b.  Set the LexicalEnvironment to the same value as the LexicalEnvironment of the calling execution
context.
c.  Set the VariableEnvironment to the same value as the VariableEnvironment of the calling execution
context.

15.3.2.1 new Function (p1, p2, … , pn, body)
Return a new Function object created as specified in 13.2 passing P as the FormalParameterList and body as
the FunctionBody. Pass in the Global Environment as the Scope parameter and strict as the Strict flag.

 

1
0
分享到:
评论
2 楼 lifesinger 2010-07-08  
楼主很厚道,不光给了中文,还给英文 ref
1 楼 xiongzhijian51 2010-02-04  
楼主不厚道,本来是不懂来学习的.还要我们自已去看英文文档.

相关推荐

    CSHARP_EVAL_FUNCTION

    在C#中实现类似JavaScript的`eval()`功能,需要通过编译和运行代码字符串来实现。这涉及到对C#语法的理解、代码编译以及代码执行等多个步骤。 首先,我们需要了解C#的语法结构。C#是一种类型安全、面向对象的编程...

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

    如果在`eval()`的字符串参数中存在这些字符,它们会被解释为代码的分隔符,可能导致代码执行错误或不按预期运行。因此,我们首先需要移除这些字符。可以使用以下正则表达式进行替换: ```javascript var ...

    JS中注入eval, Function等系统函数截获动态代码

    现在很多网站都上了各种前端反爬手段,无论手段如何,最重要的是要把包含反爬手段的前端javascript代码加密隐藏起来,然后在运行时实时解密动态执行。 动态执行js代码无非两种方法,即eval和Function。那么,不管...

    ASP执行字符串语句

    本文将详细介绍如何在ASP中利用`Eval()`函数将字符串当作语句来执行,以及这一功能的应用场景与注意事项。 #### 一、Eval()函数概述 在ASP中,`Eval()`函数是一个非常强大的工具,它能够解析并执行一个字符串中的...

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

    当`eval()`接收到一个字符串参数时,它会尝试将这个字符串解释为JavaScript代码,并执行这些代码。例如,假设我们有一个变量`code`存储了一段JavaScript,我们可以用`eval(code)`来执行这段代码。这种动态执行的能力...

    Java直接运行JS代码

    在Java编程环境中,有时我们需要与JavaScript交互,例如执行一些动态脚本或者利用JavaScript库的功能。Java提供了这样的能力,让我们可以直接在Java程序中运行JS代码。这主要得益于Oracle公司在Java 6版本引入的一个...

    在Javascript中Eval函数的使用?

    当从不可信的源获取代码时,使用`eval()`可能会导致恶意代码执行,因为它可以完全访问调用它的作用域,包括读取或修改变量、调用函数甚至控制整个应用程序。因此,除非绝对必要,否则应避免使用`eval()`。 此外,`...

    javascript 自定义eval函数实现

    首先,`eval()`的默认行为是将其接收到的字符串当作JavaScript代码执行,这可能导致潜在的安全问题,如代码注入攻击。因此,如果需要自定义`eval()`,首要目标就是增强安全性。一种方法是限制执行的上下文,例如,...

    C#和Javascript动态执行代码

    `eval()`会将字符串作为JavaScript代码执行,但因其安全风险(如执行恶意代码),通常不建议在生产环境中使用。 2. **Function构造函数**:另一种方式是使用`Function`构造函数创建新的函数对象,然后调用这个函数...

    前端开源库-safe-eval

    在前端开发中,JavaScript的`eval()`函数是一个强大的工具,它可以将字符串转化为可执行的代码。然而,由于其潜在的安全风险,直接使用`eval()`往往被开发者视为禁忌。"前端开源库-safe-eval"就是为了解决这个问题而...

    js中eval()函数和trim()去掉字符串左右空格应用.docx

    这段代码会弹出一个包含“Hello World”的警告框,因为`eval()`将字符串`"alert('Hello World')"`解析为JavaScript代码并执行。 **1.2 功能详解** - **执行代码块**:可以执行复杂的代码逻辑。 - **计算表达式**:...

    在网页中实现运行代码-复制代码-收藏代码-另存代码框效果

    在“运行代码”功能中,JavaScript可以接收用户输入的代码,然后在浏览器环境中执行这段代码(例如使用`eval()`函数或`new Function()`构造函数)。为了安全考虑,通常会使用沙盒环境,如`&lt;iframe&gt;`或者使用Web ...

    java执行JavaScript代码

    使用`ScriptEngine`的`eval()`方法可以执行JavaScript字符串: ```java String jsCode = "var x = 5; var y = 10; var result = x + y;"; engine.eval(jsCode); ``` 4. **获取JavaScript变量** 可以通过`...

    How to make D.eval invoke the user-defined function callback

    当代码执行完成后,D.eval会调用这个回调,将执行结果或任何需要的信息传递回给调用者。这允许开发者在运行时动态地添加功能或改变程序的行为。 例如,以下是一个简单的JavaScript示例,展示了如何使用类似的eval...

    javascirpt 在textarea中运行(自己学习)

    当我们想要在`&lt;textarea&gt;`内执行JavaScript代码时,这涉及到一个交互性与安全性的议题。 在HTML文档中,`&lt;textarea&gt;`标签通常这样定义: ```html &lt;textarea id="codeInput" rows="10" cols="30"&gt;&lt;/textarea&gt; ``` ...

    【基础篇】第09篇:PHP代码审计笔记--代码执行漏洞1

    - **风险**: 攻击者可以通过构造特殊的替换字符串来触发代码执行。 - **示例**: ```php // 示例代码 //?cmd=phpinfo() @preg_replace("/abc/e", $_REQUEST['cmd'], "abcd"); ?&gt; ``` 4. **`create_...

    eval用途

    上述示例中,`code`变量包含了待执行的JavaScript代码字符串,通过`eval`函数将其转换为实际的代码执行。 ##### 2. 解析复杂表达式 在解析用户输入或其他复杂表达式时,`eval`可以用来计算这些表达式的值。比如: ...

    javascript代码讲解ppt

    如果没有调用上下文,则视为全局代码执行。`this`值与调用上下文的`this`值相同。 #### 执行环境中有趣的案例分析 1. **With语句与this值**:在某些情况下,使用`with`语句可能会改变`this`值的指向,从而导致意外...

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

    这使得开发者能够在运行时动态地创建和执行代码。 ##### 2. 语法 ```javascript eval(strScript) ``` - **参数**: - `strScript`:必需。一个字符串,表示要执行的JavaScript代码。 ##### 3. 使用说明 - **...

Global site tag (gtag.js) - Google Analytics