window.execScript与eval的介绍

eval()函数的介绍

eval函数可以执行js代码字符串。eval是顶级函数,跟任何对象没有关系。eval的参数是一个字符串,如果这个字符串表示的是一个表达式,那么eval函数会对它进行求值计算。如果eval的参数不是字符串,eval会原样返回。

eval(new String("2 + 2"));

 // 返回了包含"2 + 2"的字符串对象

eval("2 + 2"); // returns 4

eval直接调用执行js代码,会根据当前上下文环境执行代码,也就说直接调用eval,比如在函数内调用,那么js代码字符串中的变量会成为函数的局部变量。而间接调用eval执行js代码,会是在全局环境上下文中执行代码。这个很有用。

function test() {

  var x = 2, y = 4;

  console.log(eval("x + y")); 

 // 直接调用,使用本地作用域,结果是 6

  var geval = eval;

  console.log(geval("x + y")); 

 // 间接调用,使用全局作用域,报错,因为下x,y在全局未定义

而间接调用eval的时候,我们要重新定义一个变量不太方便,所以通常我们采用window.eval()来实现间接调用eval的作用,使得js代码在全局作用域中执行,这样才跟我们的静态js代码效果一样。

像下面这样子调用eval:

(function foo() {

   window.eval('var yy = 20');

})();

但是呢,虽然ES规范中是这么定义的,但是在IE8-的低版本浏览器中,并没有按照这样实现,在IE8-中,上面两种eval间接调用的方式都不能使得代码中全局作用域中执行,它仍然和eval的直接调用的效果是一样的。

那么,在IE8-中是不是就没有办法在全局作用域中执行动态js代码了呢?

window.execScript

of course no,在IE中还有另一个跟eval相似的方法用来执行js代码字符串,它就是window.execScript方法。window.execScript方法永远是在全局作用域中执行js代码字符串,所以兼容性的eval代码如下:

function g_eval(str){

    //IE下执行

    //一定要先window.execScrit判断,因为opera这个贱人总模仿IE。

    if(window.execScript){

         window.execScript(str);

     }else {

         //非IE浏览器

         window.eval(str);

     }

 }

并且呢,在IE8-的浏览器中的eval函数有一些bug问题,所以选择window.execScript来处理IE是最佳选择。

eval 和 execScript的js引擎

文章写到上面,其实eval的使用以及介绍的差不多了,你从百度上搜索也就能找到上面那些介绍了。但是我们实际应用中eval的理解的需求比这一个要多。

其实呢,eval也好,execScript是启动js引擎来执行js代码字符串的。所以eval 或者execScript同样拥有变量悬置的特性。

像下面这段代码:

console.log("c:"+c);

var a=10,b=20,c=30;

无论是浏览器自己启动的js引擎还是通过eval,execScript启动的js引擎,他们的执行中的代码都会进行变量悬置,实际过程如下:

var a,b,c;

console.log("c:"+c);

a=10,b=20,c=30;

由于js引擎进行了变量悬置的处理,所以代码不会报错,输出的结果会是:c:undefined,这个结果结合浏览器处理过后的代码很好理解。

eval 不只可以执行简单的js表达式,它使用的就是浏览器自身的js引擎,所以我们正常写作浏览器中的js代码,都可以在eval函数中执行。

例如:

<script id="scriptstr"  type="text/babel">

function simpleDateFormat(format){

    this.formatstr=format;

    return this;

}

   simpleDateFormat.prototype={

       format:function(date){

           if(date instanceof Date){

               var dtfmt=this.formatstr;

               var my=dtfmt.match(/[yY]+/);

               var yg=4;

               var _y=date.getFullYear()+'',

                       _m=date.getMonth()+1,

                       _d=date.getDate();

               if(my && my[0] && my[0].length){

                   yg=my[0].length;

                   if(yg<=1){yg=2;}else{if(yg>=4){yg=4;}};

               }

               if(_m<10){_m='0'+_m;}

               if(_d<10){_d='0'+_d;}

               var dt1=dtfmt

               .replace(/[yY]+/i,_y.substring((4-yg),4))

               .replace(/[mM]+/i,_m).replace(/[dD]+/i,_d);

               return dt1;

 

           }else{

               return "不是有效的日期对象";

           }

 

       }

   };

$(function(){

    var simple=new simpleDateFormat("yyyy-mm-dd");

    var str=simple.format(new Date());

    console.log(str);

 

});

</script>

 

<script>

 var str=document.getElementById("scriptstr").innerHTML;

    if(window.execScript){

        window.execScript(str);

    }else {

        window.eval(str);

    }

</script>

像上面的代码,我们通过eval函数一样可以执行的,其中使用了jquery的入口函数,只要页面中引入了jquery,那么在eval中的js代码字符串,一样可以使用jquery库。而通过eval的这种特性,我们可以把框架页面中的iframe去掉,而通过ajax获取页面的字符串,对其中的js通过eval执行,就可正常执行。

而在实际应用中,如果我们的系统是像上面这样用iframe实现的,现在要想去除iframe,那么通过ajax获取页面字符串,之后用eval函数执行其中的js代码,就可以实现快速的转换。而采用eval的方法的弊端就是,会在顶层window对象上添加了很多多余无用的代码,不利于页面的优化,但是它确是一个简便的权宜实现方式。

并且eval函数中有了jquery库后,使用的频率就更少了,jquery确实很强大,jquery的html()方法设置innerHTML代码,它内部对其中的js代码字符串进行了eval处理,并且就连外链script标签也进行了处理。所以如果对eval还是理解不清,那么就用jquery的html()方法来代劳吧。

eval 结语

eval函数功能很强大,但是权限太大,是一个危险的函数,如非必要,尽量不要使用eval函数,以免被别有用心的人利用,执行一些危险的代码。但是了解掌握eval函数还是必要的,在一些特殊情况下,还是有eval的用武之地的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值