本文内容

  • eval
  • 隐藏的 eval
  • 安全问题
  • 结论
  • 参考资料

 

eval


eval 函数是一个高等级的函数,它与任何对象都无关。其参数,如果是一个字符串表达式,那么该函数计算表达式的值;如果是一个 JavaScript 语句, 则执行。通常用在一些需要动态执行的代码中。

var foo = 1;

function test() {

    var foo = 2;

    eval('foo = 3');

    return foo;

}

test(); // 3

foo; // 1

但是,eval 只在被直接调用并且调用函数就是 eval 本身时,才在当前作用域中执行。

var foo = 1;

function test() {

    var foo = 2;

    var bar = eval;

    bar('foo = 3');

    return foo;

}

 

test(); // 2

foo; // 3

上面的代码等价于在全局作用域中调用 eval,和下面两种写法效果一样:

写法一:直接调用全局作用域下的 foo 变量

var foo = 1;

function test() {

    var foo = 2;

    window.foo = 3;

    return foo;

}

 

test(); // 2

foo; // 3

写法二:使用 call 函数修改 eval 执行的上下文为全局作用域

var foo = 1;

function test() {

    var foo = 2;

    eval.call(window, 'foo = 3');

    return foo;

}

 

test(); // 2

foo; // 3

在任何情况下,我们都应该避免使用 eval 函数。99.9% 使用 eval 的场景都有不使用 eval 的解决方案。

 

隐藏的 eval


定时函数 setTimeout 和 setInterval 都可以接受字符串作为第一个参数。但是这个特性绝对不要使用,因为它们在内部使用了 eval。

function foo() {

    // 将会被调用

}

 

function bar() {

    function foo() {

        // 不会被调用

    }

    setTimeout('foo()', 1000);

}

bar();

由于 eval 在这种情况下不是被直接调用,因此传递到 setTimeout 的字符串会自全局作用域中执行; 因此,上面的回调函数使用的不是定义在 bar 作用域中的局部变量 foo。

建议不要在调用定时器函数时,为了向回调函数传递参数而使用字符串的形式。

function foo(a, b, c) { }

 

// 不要这样做

setTimeout('foo(1,2, 3)', 1000)

 

// 可以使用匿名函数完成相同功能

setTimeout(function () {

    foo(a, b, c);

}, 1000)

 

安全问题


eval 也存在安全问题,因为它会执行任意传给它的代码, 在代码字符串未知或者是来自一个不信任的源时,绝对不要使用 eval 函数。

eval 一般也较慢,因为它必须调用 JS 解释器,而很多其他构造方法都被现代 JS 引擎所优化。

jQuery 1.10.2 实现 globalEval 代码段,如下所示:

// Evaluates a script in a global context

// Workarounds based on findings by Jim Driscoll

// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context

globalEval: function( data ) {

    if ( data && jQuery.trim( data ) ) {

        // We use execScript on Internet Explorer

        // We use an anonymous function so that context is window

        // rather than jQuery in Firefox

        ( window.execScript || function( data ) {

            window[ "eval" ].call( window, data );

        } )( data );

    }

},

IE 使用 window.execScript 使脚本脱离当前闭包,在全局域内运行;Firefox 则使用 window.eval 来脱离当前闭包,直接使用 eval 在当前闭包运行。

jQuery 2.0.3 实现 globalEval 代码段,若是 code 标记为严格模式,则采用注入方式;否则采用 eval,如下所示:

// Evaluates a script in a global context

globalEval: function( code ) {

    var script,

            indirect = eval;

 

    code = jQuery.trim( code );

 

    if ( code ) {

        // If the code includes a valid, prologue position

        // strict mode pragma, execute code by injecting a

        // script tag into the document.

        if ( code.indexOf("use strict") === 1 ) {

            script = document.createElement("script");

            script.text = code;

            document.head.appendChild( script ).parentNode.removeChild( script );

        } else {

        // Otherwise, avoid the DOM node creation, insertion

        // and removal by using an indirect global eval

            indirect( code );

        }

    }

},

ext js 1.6 关于 eval 的代码段,如下所示:

/**

 * Compiles the template into an internal function, eliminating the RegEx overhead.

 * @return {Ext.Template} this

 */

compile : function(){

    var me = this,

        sep = Ext.isGecko ? "+" : ",";

 

    function fn(m, name){

        name = "values['" + name + "']";

        return "'"+ sep + '(' + name + " == undefined ? '' : " + name + ')' + sep + "'";

    }

 

    eval("this.compiled = function(values){ return " + (Ext.isGecko ? "'" : "['") +

         me.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +

         (Ext.isGecko ?  "';};" : "'].join('');};"));

    return me;

},

 

结论


绝对不要使用 eval,任何使用它的代码都会在它的工作方式,性能和安全性方面受到质疑。如果一些情况必须使用到 eval 才能正常工作,首先它的设计会受到质疑,这不应该是首选的解决方案, 一个更好的不使用 eval 的解决方案应该得到充分考虑并优先采用。

只要知道写 JavaScript 代码当使用 eval 时,存在这个问题就行,毕竟现在直接用 JavaScript 库比较多,安全性能好很多。

 

参考资料


 

下载 Demo

JavaScript 为什么不要使用 eval的更多相关文章

  1. JavaScript常用函数之Eval()使用

    eval() 功能:首先解释Javascript代码  然后执行它 用法:Eval(codeString) codeString是包含有javascript语句的字符串,在eval之后使用Javasc ...

  2. javascript中apply和eval结合的强大用法

        eval是一个函数,可以接受一个参数,这个参数可以作为js语句被解释性的执行,利用这个特性,eval和apply结合起来,可以大大简化代码  如下例子 <a class="cl ...

  3. JavaScript 之 解码类似eval(function(p,a,c,k,e,d){}))的JavaScript代码

    这里以解码百度访问统计代码构造函数为示例: 以下为要统计JavaScript源码:红色加粗部分将是要修改的地方. eval(function(p,a,c,k,e,d){e=function(c){re ...

  4. JavaScript中,为什么eval和with会有性能问题?

    词法作用域 词法作用域意味着作用域是由书写代码时函数声明的位置来决定的.编译的词法分析阶段 基本能够知道全部标识符在哪里以及是如何声明的,从而能够预测在执行过程中如何对它 们进行查找. eval(.. ...

  5. JavaScript基础避免使用eval()(006)

    许多人认为eval()方法是邪恶(evil)的.这个方法可以把任意字符串当成Javascript代码来执行.我们应该尽可能的不用eval()方法.比如,可以使用方括号来得到对象属性的值: // ant ...

  6. javascript JSON.parse和eval的区别

    SON.parse()用来将标准json字符串转换成js对象:eval()除了可以将json字符串(非标准的也可以,没有JSON.parse()要求严格)转换成js对象外还能用来动态执行js代码.例如 ...

  7. javascript eval和JSON之间的联系

    原出处:http://www.jb51.net/article/21688.htm eval函数的工作原理 eval函数会评估一个给定的含有JavaScript代码的字符串,并且试图去执行包含在字符串 ...

  8. JavaScript中Eval()函数的作用

    这一周感觉没什么写的,不过在研究dwz源码的时候有一个eval()的方法不是很了解,分享出来一起学习 -->首先来个最简单的理解 eval可以将字符串生成语句执行,和SQL的exec()类似. ...

  9. JavaScript中的eval()函数

    和其他很多解释性语言一样,JavaScript同样可以解释运行由JavaScript源代码组成的字符串,并产生一个值.JavaScript通过全局函数eval()来完成这个工作. eval(“1+2” ...

随机推荐

  1. 什么是套接字(Socket)

    应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要 通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连 ...

  2. apache 允许 访问软链接 ( Apache won't follow symlinks (403 Forbidden) )

    当我们在 apache 中 进行访问 www 文件夹之外的目录的时候,我们可以使用软链接的方式来进行协助访问. 我在 html 文件夹 下面创建 了 如下软链接 link: [root@dhcp-- ...

  3. [WPF]DropShadowEffect导致Image模糊问题

    实现鼠标在图片上时,图片外侧有发光效果,如上图 可使用触发器修改Image控件的Effect属性 <Style.Triggers> <Trigger Property="I ...

  4. Python接口自动化--post提交的四种数据类型 4

    常见的post请求提交的数据类型有四种: 1.第一种:application/json:这是最常见的json格式,如下 {"input1":"XXX",&quo ...

  5. C#演化过程--各个版本新增加特性

  6. js 判断元素是否在列表中

    /** * 使用循环的方式判断一个元素是否存在于一个数组中 * @param {Object} arr 数组 * @param {Object} value 元素值 */ function isInA ...

  7. 【转】ios tableView那些事(一)创建一个简单的tableView

    工作也有半年多了!几乎每个项目中的会用到tableview这个神奇而好用的控件,在学习和工作中都会看别人的博客!对我有很大的帮助,就如同站在巨人的肩膀上的感觉吧 哈哈!于是决定重新开始写博客,希望能帮 ...

  8. Qt Creator无法debug,报错:The selected debugger may be inappropriate for the inferior. Examining symbols and setting breakpoints by file name and line number may fail. The inferior is in the Portable ...

    看到这个报错我是绝望的 解决:下载windows sdk  win10 sdk 只安装Debugging Tools for Windows 打开 工具-选项-Kits 安装sdk成功后我们可以看到 ...

  9. OpenCV——反向投影(定位模板图像在输入图像中的位置)

    反向投影: #include <opencv2/opencv.hpp> #include <iostream> using namespace cv; using namesp ...

  10. leetcode322—Coin Change

    You are given coins of different denominations and a total amount of money amount. Write a function ...