本文内容

  • 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. IIS日志导致磁盘被占满

    某服务器只部署了个IIS,应用目录都在D盘,可C盘97.5GB空间却被占满了. 将系统文件,隐藏文件全部显示,再选中所有的C盘文件及文件夹查看容量只有19GB. 既然只部署了IIS,那自然就怀疑到了I ...

  2. 纯js实现页面返回顶部的动画

    啥也不说了,直接上代码 var scrollTop = document.body.scrollTop; document.body.style.marginTop = -scrollTop + 'p ...

  3. JBoss 7 里一个EJB依赖其他jar的几种方式

    JBoss 7 与之前的版本有了巨大的变化,最核心的类的加载方式变了,有点类似OSGI那样搞起来了分模块的类加载方式,而不是以前的分层类加载.按以前的类加载方式,在加载树底下的那些类,总是能看到父节点 ...

  4. jboss eap6.1(4)(部署应用)

    1.添加应用war包 手动部署,添加war包到standalone\deployments下,手工创建一个文件,如war包名称是a.war,创建一个a.war.deployed文件,内容随意. 2.  ...

  5. 【9】python关于os模块与os.path的相关操作

    ---恢复内容开始--- #__author:"吉*佳" #date: 2018/10/20 0020 #function: # os模块知识点 import os # 获取平台名 ...

  6. Python接口自动化--requests 1

    # _*_ encoding:utf-8 _*_ import requests #请求博客园首页,无参数的get请求 r = requests.get('http://www.cnblogs.com ...

  7. Math.min() / Math.max() 使用方法

    首先弄懂apply 和 call 都是js函数自带的方法.区别如下: apply和call的用法只有一个地方不一样,除此之外,其他地方基本一模一样 1. a.call(b,arg1,arg2…) 2. ...

  8. python第三十六课——2.迭代器对象

    满足前提: 1).必须是一个可迭代对象 2).可以被next()所作用的 举例: generator... 高效的检测一个对象是否是迭代器对象 需要使用collections模块中的Iterator类 ...

  9. Python第三方模块--requests简单使用

    1.requests简介 requests是什么?python语言编写的,基于urllib的第三方模块 与urllib有什么关系?urllib是python的内置模块,比urllib更加简洁和方便使用 ...

  10. PReLU与ReLU

    PReLU激活函数,方法来自于何凯明paper <Delving Deep into Rectifiers:Surpassing Human-Level Performance on Image ...