zoukankan      html  css  js  c++  java
  • eval 的使用与延展

    前些日子用到了eval()处理json数据,习惯于每次添加'('+json+')'处理数据,也没去深究为什么这么做,刚好同事问我这个问题,瞬间哑口无言,只会如何操作,却讲不出原因,这不符合咱程序员严谨的工作态度,仔细思考了一会,简略的谈谈吧。

    可能会随时脑洞,望各位见谅。

      1.什么是json?

      JSON(JavaScript Object Notation) 是一种轻量级的数据交换格式,是一种取代XML的数据结构,和xml相比,它更小巧但描述能力却不差,由于它的小巧所以网络传输数据将减少更多流量从而加快速度。

    • JSON就是一串字符串 只不过元素会使用特定的符号标注,其书写格式是:名称/值对。
      {"name":"json"} 
    • {} 双括号表示对象
    • [] 中括号表示数组
    • "" 双引号内是属性或值      

        现在还有很多人存在一些误区,为什么{name:'json'}在检验时通过不了,

      那是因为JSON官网最新规范规定

      如果是字符串,那不管是键或值最好都用双引号引起来,所以上面的代码就是 {"name":"json"}

      不要反驳,官网就是这么定义的。

    • : 冒号表示后者是前者的值(这个值可以是字符串、数字、也可以是另一个数组或对象);  

      2. 如何解析json?

      如果从后台接收json数据时,jquery将type设为'json',或者利用$.getJSON()获取,此时接收到的json是对象格式,不需要特殊处理,可直接使用;

      但是如果接收的json格式是字符串类型,这时就需要将其转换成对象格式了,两种方法:eval() 和 new Function();

    1. eval

      var json='{"name":"lee","age":"15"}'
      str=window.eval('('+ json+')');

     

    结果如图:

    我们可以看出解析后的json数据格式为对象,方便我们的后续操作处理,但是,我们为什么要用'('+json+')'这样的处理呢?

    个人拙见如下:首先eval 可将字符串解析为

      • 具体的对象
      • 求表达式的值
      • 执行语句
      • 求值
      • 处理日期数据

    还记得json的格式吗?以"{"开头对吧,在此那么你还记的语句块的格式吗?也是以"{"开头是吧,那么问题就来了,eval解析时会把我们的json当成语句块,而且这个所谓的语句块里还有":",那么极有可能会报错,如图:

    在此随便扯一点别的知识点。。

    表达式与语句

    表达式:表达式,是由数字、算符、数字分组符号(括号)、自由变量和约束变量等以能求得数值的有意义排列方法所得的组合。约束变量在表达式中已被指定数值,而自由变量则可以在表达式之外另行指定数值。

    语句:JavaScript 语句向浏览器发出的命令。语句的作用是告诉浏览器该做什么。通常我们在每条可执行的语句结尾添加分号以分隔 JavaScript 语句,多条语句构成语句块。

    有些时候,表达式和语句会看不出区别,但其作用做不同,即有一些表达式会出现在语句的上下文中,为了解决歧义,JavaScript语法禁止表达式以大括号"{"或关键字"function"开头,如果要以"{"开头的表达式能被正确解析,需要把这个"{}"包裹的内容放在"()"中,确保表达式被解析在表达式上下文中,如果表达式被解析在表达式上下文中,此时json解析后会转换成对象类型,这就是我们想要的结果。

    表达式与语句的交集:

                

    好了,原理讲解完成,那么各位应该明白以'('+json+')'格式处理eval接收数据的原理了吧,如果实在不明白,那就偷个懒,每次都不加'('+json+')',报错了再加上,时间长了也就能明白了(千万别听我的,我开玩笑的%>_<%)。

    但是,but,各位有没有听过前辈们讲过一段话:

    对于eval,要理解它,远离它。

    为什么呢?

    为什么执行会缓慢呢? 这就要引出另一位主角了:new  Function();

    2.new Function

      先扯些别的,定义函数有三种方式,分别为

    • 函数声明  function fn( arg ) {}
    • 函数表达式 var fn=function( arg ) {};
    • new     var fn=new Function(arg1,arg2...argn,body);   ps:此处的arg参数必须是字符串形式,body为函数体,同样为字符串形式

    来看代码:

    //1.取最大值
    var getMax=new Function('Math.max(arguments)');
    var max=getMax(1,4,5);
    //2.处理json数据
    var json='{"name":"json","age":"18"}';
    data=(new Function('','return'+json))();
    console.log(data);

     

     结果如图:  

     

    我们再来看看所谓的代码执行缓慢的问题是什么,直接上代码解释:

    // 1.eval
        function evalFun (){
            var start= (new Date).getTime();
            var func=eval('(function(a,b,c,d,e,f,g){return a*b*c*d*e*f*g;})');
            var result= func(4234,3424,4234,4324,423,34234,53453);
            console.log(result);
            var time=  (new Date).getTime()-start;
            return time;
        }
    
    //  2.new Function
        function newFun (){
            var start= (new Date).getTime();
            var func=new Function(['a','b','c','d','e','f','g'],'return a*b*c*d*e*f*g;');
            var result=func(4234,3424,4234,4324,423,34234,53453);
            console.log(result);
            var time=  (new Date).getTime()-start;
            return time;
    }
        t1=evalFun();//输出处理时间差,单位ms
        t2=newFun();
        console.log('时间比(new Function/eval):'+ t2/t1);    //两者时间对比

     

    两种方法所处理数据相同,结果相同,请看时间比:

    结果清晰明了,差别很大是吧,各位看官,您看懂了吧。

    最后:鄙人才疏学浅,在此献丑了,望各位前辈批评指正,在此感谢!------(未完待续)                                      2016-04-05

     

            

     

     

     

  • 相关阅读:
    SNOI 2019 字符串
    1068: [SCOI2007]压缩
    POJ 1848 Tree 树形DP
    BZOJ bzoj1396 识别子串
    BZOJ 4503: 两个串
    BZOJ 2302: [HAOI2011]Problem c(数学+DP)
    BZOJ 3157: 国王奇遇记 (数学)
    CF_528D
    BZOJ 3000: Big Number (数学)
    新の开始
  • 原文地址:https://www.cnblogs.com/delicate/p/5350260.html
Copyright © 2011-2022 走看看