javascript eval(func())

eval的作用其实很简单,就是把一段字符串传递给JS解释器,由Javascript解释器将这段字符串解释成Javascript代码,并且执行他。

  举个最简单的例子:

    <script type="text/javascript">
        eval("alert(1+1)");
    script>

  很简单,把字符串解释成JS代码并执行,弹出2。

  当然,上面的例子只是个玩具,在实际中没有人会傻到这么用。我想大家最基本的使用eval函数都是应该在DOM中,例如我们有div1,div2,div3,那么在document.getElementByID时我们的ID没有办法去得到,那么最简单的办法就是在for循环中,使用eval来拼接这么一段程序。例如这样:

    <script type="text/javascript">
        for (var loop = 1; loop < 10; loop++) {
            eval('document.getElementById("div"+loop).innerHTML="123"');
        }
    script>

  最基本的用法说完,相信大家还是对这个函数意犹未尽,如果这个函数只有这么点用法,那就太无聊了。那我们就一点点来剖下一下eval()函数。

  我们就先从eval的作用域说起,先看这样一段函数:

    <script type="text/javascript">
        eval("var i=3");
        alert(i);
    script>

  代码很简单,结果可以弹出3。接下来再对比这段代码:

    <script type="text/javascript">
        var test = function () {
            eval("var i=3");
            alert(i);
        }
        test();
        alert(i);
    script>

  结果是首先弹出3,然后是undefined。

  那么说明:eval()函数动态执行的代码并不会创建新的作用域,其代码就是在当前的作用域执行的。因此也就是说,eval()函数也完全可以使用当前作用域的this,argument等对象。

  在IE中,支持这样一种和eval()非常类似的函数叫做:execScript()。我们可以来写段简单的代码。

    <script type="text/javascript">
        var test = function () {
            execScript("var i=3");
            alert(i);
        }
        test();
        alert(i);
    script>

  结果弹出了2个3,这也就看出了execScript函数的特点,首先他和eval相类似,都能将字符串解释成JS代码并且执行,但是他的作用域不是当前作用域,而是全局作用域。当我们把上面的代码放到Firefox和谷歌浏览器上去试试:发现在Firefox上execScript上代码是无效的,那么也说明一个问题,execScript代码的浏览器兼容性是有问题的。

  那么就引申出这样一个问题,我们如何能把这两个函数的“优点”给汇总到一起呢,也就是说,全局+浏览器兼容性。上网搜了下,自己给汇总了一下,大概是这样:

    <script type="text/javascript">
        var StrongEval = function (code) {
            if (window.navigator.userAgent.indexOf("MSIE") >= 1) {
                execScript(code);
            }
            if (window.navigator.userAgent.indexOf("Firefox") >= 1) {
                window.eval(code);
            }
            else {
                execScript(code);
            }
        };
        var Test = function () {
            StrongEval("var i=3");
        }
        Test();
        alert(i);
    script>

  这样就可以完美地兼容FF和IE了,其本质代码就在于在FF中eval和window.eval并不等效,这是个很奇妙的事。

  另外,我们还可以用eval+with实现一些奇淫技巧。

  我们在一般意义上可以写出这样的代码:

var obj = function () {
    this.a = 1;
    this.b = 2;
    this.c = 5;
    this.fun = function () {
        this.c = this.a + this.b;
    }
};
var o = new obj();
o.fun();
alert(o.c);

  或者是这样:

var obj = {
    a: 1,
    b: 2,
    c: 5,
    fun: function () {
        this.c = this.a + this.b;
    }
}

  再或者是这样:

var obj = function () {
    this.a = 1;
    this.b = 2;
    this.c = 5;
};
obj.prototype.fun = function () {
    this.c = this.a + this.b;
}
var o = new obj();
o.fun();
alert(o.c);

  无论怎么样,你是不是对这样的this感觉厌烦了呢?那就让我们采取个很另类的办法吧,让至少在感官上可能会舒服一点。

    <script type="text/javascript">
        var funtemp = function () {
            c = a + b;
        }
        var obj = {
            a: 1,
            b: 2,
            c: 5
        };
        var fun;
        with (obj) {
            eval("fun = " + funtemp);
        }
        fun();
        alert(obj.c);
    script>

  这个很勉强,那么好,我们不讨论什么看着舒服不舒服。我们来讨论这样一种情况。

    <script>
        var DBCommon = function () {
            alert("1."); CreateConnection();
            alert("2."); OpenConnection();
            alert("3."); CreateCommand();
            alert("4."); ExcuteCommand();
            alert("5."); CloseConnection();
        }
        var SQLServerCommon = {
            CreateConnection: function () { alert("建立SQL Server连接"); },
            OpenConnection: function () { alert("打开SQL Server连接"); },
            CreateCommand: function () { alert("创建¨SQL Server命令"); },
            ExcuteCommand: function () { alert("执行DSQL Server命令"); },
            CloseConnection: function () { alert("关闭SQL Server连接"); }
        };
        var OracleCommon = {
            CreateConnection: function () { alert("建立¢Oracle连接"); },
            OpenConnection: function () { alert("打开aOracle连接"); },
            CreateCommand: function () { alert("创建¨Oracle命令"); },
            ExcuteCommand: function () { alert("执行DOracle命令"); },
            CloseConnection: function () { alert("关闭?Oracle连接"); }
        };
        with (SQLServerCommon) {
            eval("forSQLServer=" + DBCommon);
        }
        with (OracleCommon) {
            eval("forOracle=" + DBCommon);
        }
        forSQLServer();
        forOracle();
    script>

  我们又是否可以把这个看成是一个简陋的模板方法模式呢?呵呵。我们也可以把这个称为利用eval和with配合改变函数的上下文。

  不过话又说回来,Eval在一般的情况中是很少被用到的,我们是完全可以避免来使用它的。

<think>我们参考了多个关于JavaScript eval()函数的引用资料,结合这些信息,下面将详细讲解eval()函数的使用方法、注意事项及替代方案。 ### eval()函数的基本用法 `eval()` 是JavaScript中的一个全局函数,用于将传入的字符串作为JavaScript代码执行。其基本语法为: ```javascript eval(string) ``` 其中,`string` 参数是一个表示JavaScript表达式、语句或序列的字符串。例如: ```javascript console.log(eval('2 + 2')); // 输出:4 const x = 10; eval('console.log(x + 5)'); // 输出:15 ``` 根据引用[3],`eval` 会返回字符串中最后一条语句的返回值。如果最后一条语句没有返回值,则返回 `undefined`。如果传入的不是字符串,则直接返回该值。 ### 动态执行代码 `eval()` 的核心机制(引用[2])在于动态解析字符串代码并执行。这在需要动态生成代码的场景中非常有用,例如: ```javascript const operation = prompt("请输入一个数学表达式:"); // 用户输入"2*3+4" const result = eval(operation); console.log(result); // 输出:10 ``` ### 作用域行为 引用[5]详细解释了 `eval` 的作用域机制: - 在非严格模式下,`eval` 内部声明的变量会提升到当前作用域。 - 在严格模式下(使用 `'use strict'`),`eval` 会创建一个独立的作用域,其内部变量不会影响外部。 例如: ```javascript // 非严格模式 function f() { eval('var y = 2'); console.log(y); // 输出:2 } f(); // 严格模式 function g() { 'use strict'; eval('var z = 3'); console.log(z); // 报错:z未定义 } g(); ``` ### 安全隐患与缺陷 尽管 `eval` 功能强大,但存在严重问题(引用[1][2][4]): 1. **安全风险**:若执行用户输入的字符串,可能被注入恶意代码(XSS攻击)。 2. **性能问题**:`eval` 无法被JavaScript引擎优化,执行速度慢。 3. **可读性与维护性**:动态生成的代码难以调试和维护。 ### 替代方案 引用[4]建议避免使用 `eval`,并提供以下替代方法: 1. **使用 `Function` 构造函数**: ```javascript const add = new Function('a', 'b', 'return a + b'); console.log(add(2, 3)); // 输出:5 ``` (注意:`Function` 仍有安全风险,但作用域隔离更好) 2. **JSON解析**:若处理JSON数据,使用 `JSON.parse()`: ```javascript const data = '{"name":"Alice","age":25}'; const obj = JSON.parse(data); ``` 3. **直接调用函数或属性**:动态属性访问可通过 `obj[property]` 实现,而非拼接字符串执行。 ### 最佳实践 1. 严格限制 `eval` 的使用场景,避免执行用户输入。 2. 优先使用严格模式(`'use strict'`)限制作用域。 3. 探索替代方案(如 `Function`、`JSON.parse` 等)。 §§相关问题§§ 1. 如何防止 `eval()` 引起的XSS攻击? 2. 在严格模式下使用 `eval()` 有哪些变化? 3. `eval()` 与 `new Function()` 在作用域上有何区别? 4. 能否举例说明 `eval()` 在框架或库中的合理应用场景? </think>### JavaScript `eval()` 函数使用指南 #### 一、基本用法 `eval()` 用于执行字符串形式的 JavaScript 代码,返回最后一条语句的结果: ```javascript // 执行表达式 console.log(eval('2 + 3 * 4')); // 输出 14 [^4] // 执行多条语句(返回最后一条结果) const result = eval('let x = 5; x * 2;'); console.log(result); // 输出 10 [^3] ``` > 📌 **注意**:传入非字符串参数时,`eval()` 直接返回原值: > ```javascript > eval(42); // 返回 42 [^3] > ``` --- #### 二、作用域行为 1. **非严格模式**: ```javascript function test() { eval('var y = 2'); console.log(y); // 输出 2(变量泄漏到外部作用域)[^5] } ``` 2. **严格模式(推荐)**: ```javascript 'use strict'; function test() { eval('let z = 3'); console.log(z); // 报错:z未定义(隔离作用域)[^5] } ``` --- #### 三、安全风险与替代方案 1. **安全隐患**: - 执行用户输入字符串可能导致 XSS 攻击或代码注入[^2][^4] - 示例漏洞: ```javascript eval(userInput); // 若 userInput = "alert('恶意代码')" ``` 2. **替代方案**: | 场景 | 替代方案 | 示例 | |---------------------|-----------------------------|-------------------------------| | JSON 解析 | `JSON.parse()` | `JSON.parse('{"a":1}')` | | 动态属性访问 | 方括号语法 | `obj[propertyName]` | | 函数生成 | `new Function()` | `const func = new Function('a', 'return a*2');` [^4] | --- #### 四、最佳实践 1. **避免场景**: - 用户输入处理 - 性能关键路径(`eval()` 比直接执行慢 10-100 倍[^2]) 2. **必须使用时**: - 启用严格模式:`'use strict'` - 限制字符串来源(仅可信来源) - 添加错误捕获: ```javascript try { eval(code); } catch (err) { console.error("执行失败", err); } ``` > ⚠️ **总结**:`eval()` 虽然灵活,但因 **安全漏洞**、**性能损耗** 和 **调试困难** 应尽量避免[^1][^2][^4]。优先考虑替代方案。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值