一、eval

eval()可以动态解析和执行字符串,它直接把字符串当做Javascript代码执行,我们可以利用这个特性用来进行JSON数据的解析

不过由于eval可以解析任何字符串,所以是不安全的

var a = '{"test" : 123}';
var b = eval("(" + a + ")");

二、JSON.parse

这是浏览器(除ie8以下)自带的解析json字符串的方法,JSON.parse对解析的json字符串格式要求十分严格,需要是标准格式的JSON字符串

var a = '{"test":123}';
JSON.parse(a);

三、new Function()

new Function(arg1, arg2, ...argN, function_body);

new Function可以动态解析和执行字符串,所以可以利用其构造一个自执行函数来进行JSON字符串的解析

var a = '{"test":123}';
var jo = new Function("return" + a)()

不过使用new Function会创建一个本地对象,导致内存无法进行释放,如果解析的字符串内容过多,就有可能导致很多内存在解析完成后无法释放

一个简单的测试代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<button onclick="clickFn()">ce</button>
</body>
<script>


    function clickFn() {

        for(var a = 0; a < 100000 ;a ++){
            var text = '{"test":"..."}';
//                if ( window.JSON && window.JSON.parse ) {
//                    window.JSON.parse(text);
//                }
                new Function("return " + text)();

        }
    }


</script>
</html>

其中可以将循环次数改成10,增加字符串的内容

通过谷歌浏览器的性能分析可以看出来,每次点击之后进行JSON字符串解析,内存都会增长30多M

而且可以看出增长的都是SystemObjects,没法进行释放

如图:

使用eval方法也是如此

反观使用window.JSON.parse方法就不会出现这种情况

所以推荐大家最好使用浏览器自带的JSON字符串解析方法

顺便补充一下,jquery也有JSON字符串解析的方法$.parseJSON(data)

他其实也是用了浏览器的JSON.parse方法进行解析,遇到不支持JSON.parse的再使用new Function解析

相关源码如下:

    parseJSON: function( data ) {

        // Attempt to parse using the native JSON parser first
        if ( window.JSON && window.JSON.parse ) {
            return window.JSON.parse( data );
        }

        if ( data === null ) {
            return data;
        }

        if ( typeof data === "string" ) {

            // Make sure leading/trailing whitespace is removed (IE can't handle it)
            data = jQuery.trim( data );

            if ( data ) {

                // Make sure the incoming data is actual JSON
                // Logic borrowed from http://json.org/json2.js
                if ( rvalidchars.test( data.replace( rvalidescape, "@" )
                    .replace( rvalidtokens, "]" )
                    .replace( rvalidbraces, "" ) ) ) {

                    return ( new Function( "return " + data ) )();
                }
            }
        }

        jQuery.error( "Invalid JSON: " + data );
    },

 

posted on 2018-07-23 09:19  原来活在梦里  阅读(3961)  评论(0)    收藏  举报